英文:
How to define a type constraint for any channel type
问题
我正在尝试定义一个函数,该函数返回给定通道使用率的百分比:
func ChannelUsagePct[T any](channel chan T) int {
channelCap := cap(channel)
channelLen := len(channel)
if channelCap == 0 {
// 无缓冲通道
return 0
}
return 100 * channelLen / channelCap
}
func main() {
twoWayChannel := make(chan int, 10)
var sendOnlyChannel chan<- int = twoWayChannel
var recvOnlyChannel <-chan int = twoWayChannel
fmt.Println(ChannelUsagePct(twoWayChannel))
fmt.Println(ChannelUsagePct(sendOnlyChannel)) // 不起作用
fmt.Println(ChannelUsagePct(recvOnlyChannel)) // 不起作用
}
现在的问题是,这个函数对于第一个通道有效,但对于第二个和第三个通道无效,而不改变函数的签名。但是,如果我改变签名,我需要选择通道是只接收还是只发送。有没有一种定义零通道的方法?例如,不能读取也不能写入,我只想在其上使用cap
和len
函数。
理想情况下,ChannelUsagePct
应该适用于这三种情况中的任何一种。
英文:
I'm trying to define a funcion that returns the percentage of usage of a given channel:
func ChannelUsagePct[T any](channel chan T) int {
channelCap := cap(channel)
channelLen := len(channel)
if channelCap == 0 {
// Unbuffered channel
return 0
}
return 100 * channelLen / channelCap
}
func main() {
twoWayChannel := make(chan int, 10)
var sendOnlyChannel chan<- int = twoWayChannel
var recvOnlyChannel <-chan int = twoWayChannel
fmt.Println(ChannelUsagePct(twoWayChannel))
fmt.Println(ChannelUsagePct(sendOnlyChannel)) // Does not work
fmt.Println(ChannelUsagePct(recvOnlyChannel)) // Does not work
}
Now the thing is that this works for the first channel but not for the second and third, without changing the func's signature. But if I change the signature, I need to either choose the channel to be receive only, or send only. Is there a way to define a channel that is zero-way? E.g. cannot be read nor written to, I just want to use cap
and len
funcs on it.
Ideally the ChannelUsagePct
should work for any of the 3 cases.
答案1
得分: 3
为了允许通道的三种可能形式,需要定义一个单独的类型约束。
type Chan[T any] interface {
chan T | <-chan T | chan<- T
}
当使用时,需要使用类型参数将类型约束实例化为T
的类型:
func Cap[T any, C Chan[T]](c C) int {
return cap(c)
}
由于实例化的存在,无法推断整个类型,只需要提供通道元素类型:
ch := make(chan int, 3)
i := Cap[int](ch)
fmt.Println(i)
// 3
https://go.dev/play/p/1lx5R4MFvFx
英文:
In order to allow all three possible forms of a channel, a separate type constraint needs to be defined.
type Chan[T any] interface {
chan T | <-chan T | chan<- T
}
This will require instantiating the type constraint with the type of T
when it's used, which can be done with another type parameter:
func Cap[T any, C Chan[T]](c C) int {
return cap(c)
}
Because of that instantiation the entire type cannot be inferred, but only the channel element type needs to be supplied:
ch := make(chan int, 3)
i := Cap[int](ch)
fmt.Println(i)
// 3
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论