在Go中获得访问通道长度的正确方法

时间:2017-04-18 20:42:05

标签: go concurrency channel

我一直在使用Go,并且每天都在变得越来越好,但本身并不是专家。目前我正在处理并发和goroutines,因为我认为这是我的Go工具带中的最终未知数。我想我已经掌握了它,但仍然绝对是初学者。

我遇到问题的任务对我来说似乎很基础,但我尝试过的任何工作都没有。我想找出一种计算通道长度的方法。

根据我收集的内容,len()仅适用于缓冲通道,因此在这种情况下无法帮助我。我正在做的是批量读取数据库中的值。我有一个类似于

的生成器函数
func gen() chan Result {
  out := make(chan Result)

  go func() {
    ... query db
    for rows.Next() {
      out <- row
    }
     close(out)
   }()

  return out
}

然后我正在使用它

c := gen()

...

// do other stuff

我想要使用out通道返回计数,或者将所有它包装在struct类型中,然后返回它。

像这样:

c, len := gen()

或:

a := gen()

fmt.Println(a.c)
fmt.Println(a.len)

我相信我已经尝试了除了使用原子之外的所有东西,我认为它实际上可以工作但是我读到了它并且显然使用原子是不正确的。我还有什么其他选择,要么不留0或无限阻挡

谢谢!

3 个答案:

答案 0 :(得分:1)

len内置将返回&#34;长度&#34;频道:

  

func len(v Type)int

     

len内置函数根据其类型返回v的长度:

Array: the number of elements in v.
Pointer to array: the number of elements in *v (even if v is nil).
Slice, or map: the number of elements in v; if v is nil, len(v) is zero.
String: the number of bytes in v.
Channel: the number of elements queued (unread) in the channel buffer;
     

如果v为nil,则len(v)为零。

但我认为这对你没有帮助。

您真正需要的是解决问题的新方法:计算频道中队列中的项目不是处理&#34;批次&#34;任务。

你需要这个长度是什么?

答案 1 :(得分:0)

我假设,从你的后续答案中,你真的想知道&#34;好&#34;工作池的值和通道上的缓冲区,以保持一切正常工作&#34;最佳&#34;。

这非常困难,取决于工作人员在做什么,但是在第一次猜测时,我会在运行时查看缓冲通道和工作池的最小值.GOMAXPROCS(0)。如果你有很多资源,那么你可以尽可能地“无限”。工人。

答案 2 :(得分:0)

您正在使用缓冲的频道。谢谢你???? 未缓冲的通道不占用内存。因此永远不会包含任何东西! 无缓冲通道的唯一目的是通过将元素从一个传递到另一个来实现goroutine之间的同步。而已 !

    go func(){
        c:=make(chan struct{})
        c<-struct{}{} // Definitely locked
    }()

另一个僵局

    go func(){
        c:=make(chan struct{})
        <-c // Definitely locked
        c<-struct{}{} // Never get there
    }()

使用另一个goroutine读取频道

    go func(){
        c:=make(chan struct{})
        go func(){<-c}()
        c<-struct{}{}
    }()

在您的情况下,您有一个生成器,这意味着您必须阅读该通道,直到生产者goroutine将其关闭为止。这是一个很好的设计,可确保您的goroutine不会晃来晃去。

// Read the channel until the injecter goroutine finishes and closes it.
for r := range gen() {
...
}
// goroutine inner of gen() as finished