在go(golang)函数中将通道作为参数传递的不同方法

Cha*_*ker 45 concurrency channel go

我正在阅读一些代码并说几种不同的方式来传递频道.也许他们是一样的,但我想知道是否有任何差异,因为我在网上找不到文件:

1)

func serve(ch <-chan interface{}){ //do stuff }
Run Code Online (Sandbox Code Playgroud)

2)

func serve(ch chan<- interface{}){ //do stuff }
Run Code Online (Sandbox Code Playgroud)

3)

func serve(ch chan interface{}){ //do stuff }
Run Code Online (Sandbox Code Playgroud)

4)

func server(ch *chan interface{}){ //do stuff}
Run Code Online (Sandbox Code Playgroud)

我想知道它们之间有什么区别,如果它们只是等同的方式来做同样的事情:在不同的goroutines周围传递一个通道.

注意:我知道没有理由将指针传递给chan,map或slice或函数值,因为这些都是内部包含指针的引用类型(如果您希望被调用者更改,则会出现异常引用类型标题).我提供它的唯一原因是为了完整性(即真正提供可以尝试将通道作为参数传递的每种方式,并且有希望地提出问题,引用所有方法来进行此操作并对它们进行比较).

Ric*_*777 57

我总是建议在任何可能的地方传递方向,例如

func serve(ch <-chan SomeType) { /*do stuff*/ }

func serve(ch chan<- SomeType) { /*do stuff*/ }
Run Code Online (Sandbox Code Playgroud)

通过包含箭头<-chanchan<-,您实现了三件事:

  • 您清楚地表明参数是通道的结尾.
  • 你表达清楚头被提供.
  • 您正在向编译器提供更多信息以进行检查.如果函数体尝试使用通道的错误端,则编译器可能引发错误.

这些是尽可能显示频道结束的充分理由.

您的第三种情况描述指定频道的结尾.这允许访问通道的两端,这在某些情况下是正确的,但在其他情况下可能导致意外错误.

第四种情况,将指针传递给通道,这是非常不寻常的,也许有点奇怪.如果您想更改频道,则将其作为返回参数包含在内会更加清晰.

  • 不错的答案,除了"结束"的正确术语是"方向"/"通道方向".请参阅[此处的规范](https://golang.org/ref/spec#Channel_types). (5认同)
  • 规范确实说'方向',但这对新手来说并不一定有用.使用CSP设计,人们可以松散地思考像流体管道这样的通道 - 将其一端倒入另一端,然后排出另一端.在奥卡姆,这种区别是明确的,但在Go中它(故意)更加模糊.特别是,使用Go,可以在*single goroutine*中完全使用缓冲通道,因此规范指的是方向而不是结束.在CSP中这种用法是不可能的,但是Go的渠道的实现是灵活的并允许它. (2认同)

Vol*_*ker 25

这些是不同类型的渠道.请参阅http://golang.org/ref/spec#Channel_types.对于指针的东西:不常见,但如果你想从函数内部更改通道可能会很有用(从未在野外看到过).


smi*_*hra 22

经验法则:箭头显示数据是进入(输出)还是离开(输入)通道.没有箭头是通用渠道.

chan <-          writing to channel (output channel)
<- chan          reading from channel (input channel)
chan             read from or write to channel (input/output channel)
Run Code Online (Sandbox Code Playgroud)