Re: [go-nuts] Is there a better way to write this?

130 views
Skip to first unread message

K. Alex Mills

unread,
Sep 15, 2022, 7:10:33 AM9/15/22
to Aaron Spangler, golang-nuts
The only alternatives that I see would each introduce an extra call to Add, like the below. I'm not sure if this is much less "clunky", but it at least avoids the reassignment to s.

func collectStringsetMap(m map[string]*stringset.Set, key string, value ...string) *stringset.Set {
  if s, ok := m[key]; ok {
    s.Add(value...)
    return s
  }
  newset := stringset.New()
  m[key] = &newset
  newset.Add(value...)
  return &newset
}

> Why can't I just use &(stringset.New()) ?

I'm unsure, but it might have something to do with Go being explicit and the language designers wanting to make the stack allocation and transfer to the heap explicit... or it might make Go's escape analysis feasible.

That said, you wouldn't have to worry about it if the library authors chose to return a pointer, but in that case the caller would be forced to accept a heap allocation on every stringset.New(). Returning a value has its merits here.

On Tue, Sep 13, 2022, 4:44 PM 'Aaron Spangler' via golang-nuts <golan...@googlegroups.com> wrote:
I seem to be regularly working with maps of stringsets and I have
found myself writing the same pattern over and over and I ended up
having my own utility function.  More importantly the syntax seems
clunky when a key doesn't exist in the map.  Is there a better way (go
idiomatically way) to write this?

import  "google3/third_party/golang/stringset/stringset"

var urlMap = make(map[string]*stringset.Set)

func collectStringsetMap(m map[string]*stringset.Set, key string,
value ...string) *stringset.Set {
  s, ok := m[key]
  if !ok {
    newset := stringset.New()  // Why can't I just use &(stringset.New()) ?
    s = &newset
    m[key] = s
  }
  s.Add(value...)
  return s
}

If there is a way to clean up the code, let me know.

Also why can map's just take a default function to construct items
that are not yet present?
Something like:

var urlMap = make(map[string]*stringset.Set, ...func =
defaultStringsetConstructor...)

func defaultStringsetConstructor(key string) *stringset.Set {
  n := stringset.New()
  return &n
}

Or perhaps some trickery in the map lookup?

 s, ok := m[key, defaultStringsetConstructor]

At the end of the day you want the map to save any new items that were
not already in the map, but I don't see any less clunky ways of doing
this.  (What am I missing?)

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAHP%2Bjq5zX69g5S88_G03CZyHMoC_xGPXxqZfbc%3DKg0FRi8%3DMgQ%40mail.gmail.com.

Aaron Spangler

unread,
Sep 15, 2022, 11:42:29 AM9/15/22
to K. Alex Mills, golang-nuts
A friend helped me reduce it down to this. Notice that the map now
uses stringset.Set instead of *stringset.Set. This does much of the
heavy lifting and gets around that pesky pointer issue.

func collectStringsetMap(m map[string]stringset.Set, key string, value
...string) stringset.Set {
s, ok := m[key]
s.Add(value...)
if !ok {
m[key] = s
}
return s
Reply all
Reply to author
Forward
0 new messages