英文:
Finding an item by iterating through a Go list
问题
我正在尝试将一些C代码移植到Go语言。
我基本上在寻找Go中类似于Haskell的find :: (a -> Bool) -> [a] -> Maybe a
的功能。
我有以下(大致)用于在“列表”中通过迭代查找项目的C代码:
struct foo {
struct foo *next;
char *name;
}
struct foo *foo_list;
// 省略
struct foo *foo = NULL;
for (f = foo_list; f; f = f->next) {
if (!strcmp("bar", f->name) {
foo = f;
}
}
if (foo)
// 处理
在Go中,我应该如何以一种漂亮和习惯性的方式实现这个功能?
这个“列表”可能很小,性能特征并不特别重要。
我可能需要一个slice
还是一个list
?是Foo
的“列表”还是*Foo
的“列表”?
目前我有以下代码,但我怀疑它不是特别“习惯用法的Go”!
var FooTable *list.List
// 省略
var foo *Foo = nil
for e := FooTable.Front(); e != nil; e = e.Next() {
if e.Value.(*Foo).name == "bar" {
foo = e.Value.(*Foo)
break
}
}
英文:
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
}
}
答案1
得分: 6
对于习惯用法的Go语言,你需要一个指向Foo
的指针切片(如果Foo
非常小,你也可以选择只用Foo
的切片),所以代码如下:
var foos []*Foo
然后进行搜索:
var found *Foo
for _, foo := range foos {
if foo.name == "bar" {
found = foo
break
}
}
if found != nil {
// 处理逻辑
}
如果你经常这样做,你可以将其封装成一些类型,类似这样:
type Foos []*Foo
func (fs Foos) find(what string) (foo *Foo) {
for _, foo = range foos {
if foo.name == what {
return foo
}
}
return nil
}
然后你可以这样使用:
var foos Foos
foo := foos.find("bar")
if foo != nil {
// 处理逻辑
}
PS 很高兴能回答一个我真正见过的人的问题!
英文:
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!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论