无法将 make(IntChannel)(类型为 IntChannel 的值)用作变量声明中的 Consumer 值。

huangapple go评论88阅读模式
英文:

cannot use make(IntChannel) (value of type IntChannel) as Consumer value in variable declaration

问题

我们有以下场景:

package main

type Consumer chan interface {
	OpenChannel()
	CloseChannel()
}

type IntChannel chan int
type StringChannel chan string

func (c IntChannel) OpenChannel() {

}

func (c IntChannel) CloseChannel() {

}

func (c StringChannel) OpenChannel() {

}

func (c StringChannel) CloseChannel() {

}

func main() {

	var dataChannel Consumer = make(IntChannel)
	for data = range dataChannel {

	}
}

目标是在 dataChannel 上使用 range

var dataChannel Consumer = make(IntChannel) 出现错误:cannot use make(IntChannel) (value of type IntChannel) as Consumer value in variable declaration

根据运行时给定的配置值,我们选择 int 类型的通道或 string 类型的通道。

阅读这个答案,但没有太多帮助。


如何在选择 int 数据或 string 数据的通道类型上使用 range

英文:

We have a below scenario:

package main

type Consumer chan interface {
	OpenChannel()
	CloseChannel()
}

type IntChannel chan int
type StringChannel chan string

func (c IntChannel) OpenChannel() {

}

func (c IntChannel) CloseChannel() {

}

func (c StringChannel) OpenChannel() {

}

func (c StringChannel) CloseChannel() {

}

func main() {

	var dataChannel Consumer = make(IntChannel)
	for data = range dataChannel {

	}
}

Goal is to range on dataChannel.

var dataChannel Consumer = make(IntChannel) gives error: cannot use make(IntChannel) (value of type IntChannel) as Consumer value in variable declaration

We pick int channel or string channel based on a given config value at runtime.

Read this answer, but not much help.


How to range on a channel type that picks either int data or string data?

答案1

得分: 3

首先,你将Consumer声明为chan类型的interface{ /* methods */ },这几乎肯定不是你想要的——实际上,错误提示说明你不能将IntChannel赋值给它。

然后,在语言中添加泛型之前,你没有办法保持类型安全。

最接近你想要做的解决方案可能是在接口中添加一个额外的方法,该方法返回可以进行range迭代的内容。

type Consumer interface {
	OpenChannel()
	CloseChannel()
	Range() <-chan interface{}
}

type IntChannel chan int

func (c IntChannel) OpenChannel() {
}

func (c IntChannel) CloseChannel() {
}

func (c IntChannel) Range() <-chan interface{} {
	ret := make(chan interface{})
	go func() {
		defer close(ret)
		for v := range c {
			ret <- v
		}
	}()
	return ret
}

func main() {
	c := make(IntChannel)
	var dataChannel Consumer = c
	go func() {
		c <- 12
		close(c)
	}()
	for data := range dataChannel.Range() {
		fmt.Println(data)
	}
}

Go1 Playground: https://play.golang.org/p/55BpISRVadE


使用泛型(Go 1.18,2022年初),相反,你可以定义一个具有底层类型chan的参数化类型:

package main

import "fmt"

type GenericChan[T] chan T

func main() {
	c := make(GenericChan[int])
	go func() {
		c <- 12
		close(c)
	}()
	for data := range c {
		fmt.Println(data)
	}
}

Go2 Playground: https://go2goplay.golang.org/p/HQJ36ego97i

英文:

First, you declared Consumer as a chan of interface{ /* methods */ }, which most surely isn't what you want — as a matter of fact, the error tells that you can't assign IntChannel to it.

Then, until generics are added to the language, you don't have a way to preserve type safety.

The closest solution to what you want to do might be adding an additional method to the interface that returns something that you can range over.

type Consumer interface {
	OpenChannel()
	CloseChannel()
	Range() &lt;-chan interface{}
}

type IntChannel chan int

func (c IntChannel) OpenChannel() {
}

func (c IntChannel) CloseChannel() {
}

func (c IntChannel) Range() &lt;-chan interface{} {
	ret := make(chan interface{})
	go func() {
		defer close(ret)
		for v := range c {
			ret &lt;- v
		}
	}()
	return ret
}

func main() {
	c := make(IntChannel)
	var dataChannel Consumer = c
	go func() {
		c &lt;- 12
		close(c)
	}()
	for data := range dataChannel.Range() {
		fmt.Println(data)
	}
}

Go1 Playground: https://play.golang.org/p/55BpISRVadE

<hr>

With generics (Go 1.18, early 2022), instead you can just define a parametrized type with underlying type chan:

package main

import &quot;fmt&quot;

type GenericChan[T] chan T

func main() {
	c := make(GenericChan[int])
	go func() {
		c &lt;- 12
		close(c)
	}()
	for data := range c {
		fmt.Println(data)
	}
}

Go2 Playground: https://go2goplay.golang.org/p/HQJ36ego97i

huangapple
  • 本文由 发表于 2021年8月31日 17:09:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/68995907.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定