结构体中的 Golang 通道:传递给函数时可以定向吗?

Bar*_*rim 5 struct channel go channels

将通道传递给函数时,我知道您可以指定通道可以使用通道的方向;例如,

func MyFunc(ch chan<- string) {
    ch <- "Hello"
}
Run Code Online (Sandbox Code Playgroud)

“ch”只能被 MyFunc 用来向别处的接收者发送字符串,而 MyFunc 不能监听来自 ch 的消息。

为了简化为一定数量的 goroutine 创建动态数量的通道,我创建了一个包含通道的结构。

type ChanStruct struct {
    chMessages chan string
}
Run Code Online (Sandbox Code Playgroud)

然后我实例化一个结构:

var slcChanStruct []ChanStruct
for a:= 0; a <=2; a++ {
    var tmpChanStruct ChanStruct
    tmpChanStruct.chMessages = make(chan string)
    slcChanStruct = append(slcChanStruct, tmpChanStruct)
}
Run Code Online (Sandbox Code Playgroud)

现在我有 3 个结构,我可以通过覆盖一片结构来单独读/写一个通道。但是当我将它们发送到 goroutines 时:

for a:=0; a <=2; a++{
    go SomeFunc(slcChanStruct[a])
}
Run Code Online (Sandbox Code Playgroud)

...有没有办法通过指定 goroutines 只能,例如,使用 ChanStruct.ch 通道发送来增加一点安全性?

注意我这样做的原因是,如果我不知道一组并行进程需要多少个通道(进程数作为命令行参数传递)使用带有通道的结构意味着我可以创建一个切片,可以传递给任意数量的 goroutine,并通过遍历它们直接单独访问它们;以前,如果我想从多个 goroutine 中单独读取,我必须创建一定数量的通道。我想通过指定进程只能以某种方式使用通道来增加一些安全性,就像我在使用单个通道时一样(单个通道意味着我可以做一些事情,比如告诉特定的 goroutine 在没有其他 goroutine 拦截它的情况下退出)。如果可以的话,有没有更惯用的方法来做到这一点?

abh*_*ink 4

除了@Adrian 的建议之外,如果您必须确保频道上的单向通信,您始终可以使用匿名函数:

for a:=0; a <=2; a++{
  go func f(ch <-string) {
    SomeFunc(ch)
  }(slcChanStruct[a].chMessages)
}
Run Code Online (Sandbox Code Playgroud)

请注意,您必须传递通道SomeFunc而不是结构。

如果您仍想在通道上执行双向通信,可以将通道重新分配为单向类型:

type ChanStruct struct {
    chMessages chan string
}

type ChanStructRecv struct {
    chMessages <-chan string
}

// Update SomeFunc type:

func SomeFunc(s ChanStructRecv) {
  // ...
}
Run Code Online (Sandbox Code Playgroud)

最后,可以类似地修改循环:

for a:=0; a <=2; a++{
  go func f(s ChanStruct) {
    var sr ChanStructRecv
    sr.chMessages = s.chMessages
    SomeFunc(sr)
  }(slcChanStruct[a])
}
Run Code Online (Sandbox Code Playgroud)