如何在具有接受多种类型的 chan 参数的结构上创建 func?
How to create func on a struct that has chan param which accepts multiple types?
几天来一直在研究 Go、Goroutines 和 Channels。
经过大量实践和这里的一些帮助,与 Goroutines 和错误处理相关 (),我现在遇到了一个我不知道如何解决的问题。
问题是我想创建一个 Mapper,它有一个接受任何类型的 chan
的函数。我试图通过传入 chan interface{}
而不是真实类型来解决这个我能想到的唯一方法,但这显然行不通。 (如下例所示)
所以我正在寻找执行此操作的正确方法,并确认这甚至是正确的方法。
package main
import (
"fmt"
"golang.org/x/sync/errgroup"
)
var g errgroup.Group
// ItemOne struct
type ItemOne struct {
N int
}
func main() {
m := &Mapper{}
itemsOne, err := mapItemOne(m)
if err != nil {
// Handle error...
}
fmt.Println(itemsOne)
itemsTwo, err := mapItemTwo(m)
if err != nil {
// Handle error...
}
fmt.Println(itemsOne)
}
func mapItemOne(m *Mapper) ([]*ItemOne, error){
c := make(chan *ItemOne, 10)
data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
g.Go(func() error {
return m.mapItems(c, data)
})
mappedItems := make([]*ItemOne, 0)
for elem := range c {
mappedItems = append(mappedItems, elem)
}
err := g.Wait()
if err != nil {
return nil, err
}
return mappedItems, nil
}
// ItemTwo struct
type ItemTwo struct {
N int
}
func mapItemTwo(m *Mapper) ([]*ItemTwo, error){
c := make(chan *ItemTwo, 10)
data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
g.Go(func() error {
return m.mapItems(c, data)
})
mappedItems := make([]*ItemTwo, 0)
for elem := range c {
mappedItems = append(mappedItems, elem)
}
err := g.Wait()
if err != nil {
return nil, err
}
return mappedItems, nil
}
// Mapper struct
type Mapper struct {}
func (m *Mapper) mapItems(c chan *interface{}, data []int) error {
defer close(c)
// Imagine that something here can error...
for _, v := range data {
fmt.Println(v)
item := &ItemOne{
N: v,
}
c <- item
}
return nil
}
适用的示例(ItemTwo 代码已注释掉):
https://play.golang.org/p/PlqPflP7Yf7
不起作用的示例(ItemTwo 代码在注释中):
https://play.golang.org/p/xM89GVY2BoX
我在操场上放了两个例子。第一个有效,但第二个因 ItemTwo 代码处于活动状态而损坏。
希望有人能在这里为我指明正确的方向。谢谢。
The issue is that I want to create a Mapper, that has a function which accepts a chan of any type.
你根本无法在 Go 的类型系统中做到这一点。您必须决定类型,如果类型是 interface
,则您只能使用该类型,并且所有函数签名都必须匹配。 Go中没有co/contravariance.
最佳建议:停止尝试编写通用代码。这是可行的,但它丑陋、缓慢且复杂。
几天来一直在研究 Go、Goroutines 和 Channels。
经过大量实践和这里的一些帮助,与 Goroutines 和错误处理相关 (
问题是我想创建一个 Mapper,它有一个接受任何类型的 chan
的函数。我试图通过传入 chan interface{}
而不是真实类型来解决这个我能想到的唯一方法,但这显然行不通。 (如下例所示)
所以我正在寻找执行此操作的正确方法,并确认这甚至是正确的方法。
package main
import (
"fmt"
"golang.org/x/sync/errgroup"
)
var g errgroup.Group
// ItemOne struct
type ItemOne struct {
N int
}
func main() {
m := &Mapper{}
itemsOne, err := mapItemOne(m)
if err != nil {
// Handle error...
}
fmt.Println(itemsOne)
itemsTwo, err := mapItemTwo(m)
if err != nil {
// Handle error...
}
fmt.Println(itemsOne)
}
func mapItemOne(m *Mapper) ([]*ItemOne, error){
c := make(chan *ItemOne, 10)
data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
g.Go(func() error {
return m.mapItems(c, data)
})
mappedItems := make([]*ItemOne, 0)
for elem := range c {
mappedItems = append(mappedItems, elem)
}
err := g.Wait()
if err != nil {
return nil, err
}
return mappedItems, nil
}
// ItemTwo struct
type ItemTwo struct {
N int
}
func mapItemTwo(m *Mapper) ([]*ItemTwo, error){
c := make(chan *ItemTwo, 10)
data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
g.Go(func() error {
return m.mapItems(c, data)
})
mappedItems := make([]*ItemTwo, 0)
for elem := range c {
mappedItems = append(mappedItems, elem)
}
err := g.Wait()
if err != nil {
return nil, err
}
return mappedItems, nil
}
// Mapper struct
type Mapper struct {}
func (m *Mapper) mapItems(c chan *interface{}, data []int) error {
defer close(c)
// Imagine that something here can error...
for _, v := range data {
fmt.Println(v)
item := &ItemOne{
N: v,
}
c <- item
}
return nil
}
适用的示例(ItemTwo 代码已注释掉): https://play.golang.org/p/PlqPflP7Yf7
不起作用的示例(ItemTwo 代码在注释中): https://play.golang.org/p/xM89GVY2BoX
我在操场上放了两个例子。第一个有效,但第二个因 ItemTwo 代码处于活动状态而损坏。
希望有人能在这里为我指明正确的方向。谢谢。
The issue is that I want to create a Mapper, that has a function which accepts a chan of any type.
你根本无法在 Go 的类型系统中做到这一点。您必须决定类型,如果类型是 interface
,则您只能使用该类型,并且所有函数签名都必须匹配。 Go中没有co/contravariance.
最佳建议:停止尝试编写通用代码。这是可行的,但它丑陋、缓慢且复杂。