Reputation: 38510
I'm attempting to port some C to Go.
I'm essentially looking for something in Go akin to Haskell's find :: (a -> Bool) -> [a] -> Maybe a
I have (roughly) this C for finding an item in a "list" by iterating through it:
struct foo {
struct foo *next;
char *name;
}
struct foo *foo_list;
// Snip
struct foo *foo = NULL;
for (f = foo_list; f; f = f->next) {
if (!strcmp("bar", f->name) {
foo = f;
}
}
if (foo)
// Stuff
How can I do this nicely and idiomatically in Go?
The "list" is likely to be small; performance characteristics aren't particularly interesting.
Am I likely to want a slice
, or a list
? A "list" of Foo
s or *Foo
s?
I currently have the following, but I suspect it's not particularly "idiomatic Go"!
var FooTable *list.List
// Snip
var foo *Foo = nil
for e := FooTable.Front(); e != nil; e = e.Next() {
if e.Value.(*Foo).name == "bar" {
foo = e.Value.(*Foo)
break
}
}
Upvotes: 2
Views: 105
Reputation: 54079
For idiomatic Go you want a slice of pointers to Foo
(though if Foo is very small you might choose just a slice of Foo
), so
var foos []*Foo
And then for searching
var found *Foo
for _, foo := range foos {
if foo.name == "bar" {
found = foo
break
}
}
if found != nil {
// stuff
}
If you do this a lot you'll wrap it up with some types something like this
type Foos []*Foo
func (fs Foos) find(what string) (foo *Foo) {
for _, foo = range foos {
if foo.name == what {
return foo
}
}
return nil
}
Then you can do
var foos Foos
foo := foos.find("bar")
if foo != nil {
// something
}
PS Nice to answer a question for someone I've actually met!
Upvotes: 6