结构中的 Golang 通道:传递给函数时是否可以定向?
Golang channel in a struct: Can it be directional when passed to a function?
将通道传递给函数时,我知道您可以指定通道可以使用通道的方向;例如,
func MyFunc(ch chan<- string) {
ch <- "Hello"
}
"ch" 只能由 MyFunc 用于将字符串发送到其他地方的接收器,而 MyFunc 无法侦听来自 ch.
的消息
为了简化为一定数量的 goroutine 创建动态数量的通道,我创建了一个包含通道的结构。
type ChanStruct struct {
chMessages chan string
}
然后我实例化一个结构体:
var slcChanStruct []ChanStruct
for a:= 0; a <=2; a++ {
var tmpChanStruct ChanStruct
tmpChanStruct.chMessages = make(chan string)
slcChanStruct = append(slcChanStruct, tmpChanStruct)
}
现在我有 3 个结构,我可以单独 read/write 通过在结构切片上进行范围调整来使用通道。但是当我将它们发送给 goroutines 时:
for a:=0; a <=2; a++{
go SomeFunc(slcChanStruct[a])
}
...有没有办法通过指定 goroutine 只能使用 ChanStruct.ch 通道发送来增加一点安全性?
注意我这样做的原因是,如果我不知道我需要多少个通道来使用一个带有channels 意味着我可以创建一个可以传递给任意数量的 goroutines 的切片,并通过遍历它们来直接单独访问它们;以前,如果我想从多个 goroutine 中单独读取,我必须创建一定数量的通道。我想通过指定进程只能以某种方式使用通道来增加一些安全性,就像我在使用单个通道时可以做的那样(单个通道意味着我可以做一些事情,比如告诉一个特定的 goroutine 退出而其他 goroutine 不会拦截它).如果我无法使用结构中的通道向函数添加方向性,是否有更惯用的方法来执行此操作?
几种方法,具体取决于您的具体情况:
- 传递通道而不是结构,并像第一个示例那样使通道参数具有方向性
- 不要直接暴露通道,只暴露一个struct方法写入(如果没有方法从中读取,它是有效的定向)
- 使通道结构成员具有方向性:
例如
type myStruct struct {
c chan <- bool
}
除了@Adrian 的建议之外,如果您必须确保在频道上进行单向通信,您始终可以使用匿名函数:
for a:=0; a <=2; a++{
go func f(ch <-string) {
SomeFunc(ch)
}(slcChanStruct[a].chMessages)
}
请注意,您必须将通道传递给 SomeFunc
而不是结构。
如果您仍想在您的频道上执行双向通信,您可以将频道重新分配为单向类型:
type ChanStruct struct {
chMessages chan string
}
type ChanStructRecv struct {
chMessages <-chan string
}
// Update SomeFunc type:
func SomeFunc(s ChanStructRecv) {
// ...
}
最后循环也可以类似修改:
for a:=0; a <=2; a++{
go func f(s ChanStruct) {
var sr ChanStructRecv
sr.chMessages = s.chMessages
SomeFunc(sr)
}(slcChanStruct[a])
}
将通道传递给函数时,我知道您可以指定通道可以使用通道的方向;例如,
func MyFunc(ch chan<- string) {
ch <- "Hello"
}
"ch" 只能由 MyFunc 用于将字符串发送到其他地方的接收器,而 MyFunc 无法侦听来自 ch.
的消息为了简化为一定数量的 goroutine 创建动态数量的通道,我创建了一个包含通道的结构。
type ChanStruct struct {
chMessages chan string
}
然后我实例化一个结构体:
var slcChanStruct []ChanStruct
for a:= 0; a <=2; a++ {
var tmpChanStruct ChanStruct
tmpChanStruct.chMessages = make(chan string)
slcChanStruct = append(slcChanStruct, tmpChanStruct)
}
现在我有 3 个结构,我可以单独 read/write 通过在结构切片上进行范围调整来使用通道。但是当我将它们发送给 goroutines 时:
for a:=0; a <=2; a++{
go SomeFunc(slcChanStruct[a])
}
...有没有办法通过指定 goroutine 只能使用 ChanStruct.ch 通道发送来增加一点安全性?
注意我这样做的原因是,如果我不知道我需要多少个通道来使用一个带有channels 意味着我可以创建一个可以传递给任意数量的 goroutines 的切片,并通过遍历它们来直接单独访问它们;以前,如果我想从多个 goroutine 中单独读取,我必须创建一定数量的通道。我想通过指定进程只能以某种方式使用通道来增加一些安全性,就像我在使用单个通道时可以做的那样(单个通道意味着我可以做一些事情,比如告诉一个特定的 goroutine 退出而其他 goroutine 不会拦截它).如果我无法使用结构中的通道向函数添加方向性,是否有更惯用的方法来执行此操作?
几种方法,具体取决于您的具体情况:
- 传递通道而不是结构,并像第一个示例那样使通道参数具有方向性
- 不要直接暴露通道,只暴露一个struct方法写入(如果没有方法从中读取,它是有效的定向)
- 使通道结构成员具有方向性:
例如
type myStruct struct {
c chan <- bool
}
除了@Adrian 的建议之外,如果您必须确保在频道上进行单向通信,您始终可以使用匿名函数:
for a:=0; a <=2; a++{
go func f(ch <-string) {
SomeFunc(ch)
}(slcChanStruct[a].chMessages)
}
请注意,您必须将通道传递给 SomeFunc
而不是结构。
如果您仍想在您的频道上执行双向通信,您可以将频道重新分配为单向类型:
type ChanStruct struct {
chMessages chan string
}
type ChanStructRecv struct {
chMessages <-chan string
}
// Update SomeFunc type:
func SomeFunc(s ChanStructRecv) {
// ...
}
最后循环也可以类似修改:
for a:=0; a <=2; a++{
go func f(s ChanStruct) {
var sr ChanStructRecv
sr.chMessages = s.chMessages
SomeFunc(sr)
}(slcChanStruct[a])
}