使结构"具有范围"?

won*_*ng2 7 go

type Friend struct {
    name string
    age  int
}

type Friends struct {
    friends []Friend
}
Run Code Online (Sandbox Code Playgroud)

我想制作Friends范围,这意味着,如果我有一个my_friends带有类型的变量Friends,我可以循环使用:

for i, friend := range my_friends {
    // bla bla
}
Run Code Online (Sandbox Code Playgroud)

Go有可能吗?

the*_*mue 13

朋友成为一个结构?否则就干脆做

type Friends []Friend
Run Code Online (Sandbox Code Playgroud)

  • 我认为这是一个非常好的答案.如果`Friends struct`只显示内容,则将类型定义为`type Friends [] Friend`.Go可以在类似于这种类型的方法上使用`struct`s,它与大多数语言略有不同. (2认同)

nem*_*emo 11

注意:正如deft_code所提到的,当循环中断时,此代码会泄漏通道和goroutine.不要将其用作一般模式.


在go中,没有办法使任意类型兼容range,因为 range只支持切片,数组,通道和映射.

您可以使用迭代通道range,如果您想要迭代动态生成的数据而不必使用切片或数组,这非常有用.

例如:

func Iter() chan *Friend {
   c := make(chan *Friend)
   go func() {
      for i:=0; i < 10; i++ {
        c <- newFriend()
      }
      close(c)
   }()
   return c
}

func main() {
  // Iterate 
  for friend := range Iter() {
    fmt.Println("A friend:", friend)
  }
}
Run Code Online (Sandbox Code Playgroud)

这是你能够做出"适应性"的最接近的事情.

所以通常的做法是Iter()在你的类型上定义一个方法或类似的东西并将其传递给range.

请参阅规格以进一步阅读range.

  • 当然,缺点是,与切片范围相比,使用此处的通道效率不高.每个通道读/写都可能导致运行时切换到不同的goroutine,在大多数情况下,您可以在切片上进行范围而不会被其他goroutine抢占. (2认同)
  • 如果范围没有迭代完成,这会泄漏通道和goroutine.泄漏的简单解决方案会导致比赛或死锁.完整的强大解决方案非常复杂和微妙.谷歌内部Go邮件列表的共识是这是一个反模式. (2认同)