How can I range over a channel of unknown types in golang

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

How can I range over a channel of unknown types in golang

问题

我有一个函数,它接收一个字符串,并根据该字符串值创建一个基于该字符串类型的通道。然后,这个通道被发送到另一个线程中进行填充。

在这个函数中,我想要遍历填充后的值并使用它们。

然而,我遇到了一个错误:"cannot range over myChan (type interface {})"。

以下是我的代码示例:

func myFunc(input string) {
    var myChan interface{}

    switch input {
    case "one":
        myChan = make(chan One)
    case "two":
        myChan = make(chan Two)
    }

    go doStuff(&myChan)

    for _, item := range myChan {
        fmt.Println(item)
    }
}

请帮助我理解如何解决这个问题?

编辑:很抱歉我的问题没有表达清楚。go doStuff(&myChan) 这一行实际上是这样的:

go gocsv.UnmarshalToChan(clientsFile, &myChan)

根据 gocsv UnmarshalToChan 的文档,"通道必须具有具体的类型"。这就是为什么我不能使用 chan interface{} 的原因。

英文:

I have a function which receives a string and based on that it creates a channel of a type based on the string value. This channel is then sent off to be populated in another thread.

In this function, I then want to range over the populated values and use them.

However, I get an error: "cannot range over myChan (type interface {})"

Here is an example of my code:

func myFunc(input string) {
    var myChan interface{}

    switch input {
    case "one":
	    myChan = make(chan One)
    case "two":
	    myChan = make(chan Two)
    }

    go doStuff(&myChan)

	for _, item := range myChan {
    	fmt.Println(item)
    }
}

Please help me understand how to accomplish this?

Edit: I'm sorry my question was not clear enough. The line go doStuff(&myChan) is actually this:

go gocsv.UnmarshalToChan(clientsFile, &myChan)

According to the documentation of gocsv UnmarshalToChan "The channel must have a concrete type." That is why I cannot have a chan interface{}

答案1

得分: 0

myChan变量不是一个通道,通道类型可以通过以下方式创建:

例如,如果你想要一个可以传递任意类型的通道,可以使用以下代码:

func main() {
    c := make(chan interface{}, 1)
    
    go func() {
        for a := range c {
            fmt.Println(a)
        }
    }()
    
    c <- 21
    c <- "jazz"
    c <- person{"Chet", 88}

    time.Sleep(time.Second)
}

type person struct {
    Name string
    Age  int
}

完整示例:https://play.golang.org/p/BJrAHiSAaw

英文:

myChan variable isn't a channel, a type channel is created in this way: chan interface{}

for example if you want a channel to pass any type you can use this:

func main() {
	c := make(chan interface{}, 1)
	
	go func() {
		for a := range c {
			fmt.Println(a)
		}
	}()
	
	c &lt;- 21
	c &lt;- &quot;jazz&quot;
	c &lt;- person{&quot;Chet&quot;, 88}

	time.Sleep(time.Second)
}

type person struct {
	Name string
	Age int
}

full example: https://play.golang.org/p/BJrAHiSAaw

答案2

得分: 0

我不确定我完全理解你的问题,但是根据你写的代码,这是我解决"cannot range"问题的方法。这段代码会发生死锁,因为并没有定义一切...但是遍历不应该是一个问题。另外,doStuff代码应该在通道关闭时发出信号,可以传入一个等待组,用计数器进行跟踪等等。

package main

import (
	"fmt"
	"log"
)

// One ...
type One struct{}

// Two ...
type Two struct{}

func doStuff(*interface{}) {}

func myFunc(input string) {
	var myChan interface{}
	switch input {
	case "one":
		myChan = make(chan One)
	case "two":
		myChan = make(chan Two)
	}
	// 可能需要将这行代码移到下面的switch块中...
	// 参考下面的注释示例
	go doStuff(&myChan)

	switch myChan.(type) {
	case chan One:
		// 这样你不是传递一个interface{},而是一个chan或者类型One或Two
		// go doStuff(&myChan.(chan One))
		for item := range myChan.(chan One) {
			fmt.Println(item)
		}
	case chan Two:
		// go doStuff(&myChan.(chan One))
		for item := range myChan.(chan Two) {
			fmt.Println(item)
		}
	default:
		log.Fatalln("Unknown type entered")
	}

}

func main() {
	myFunc("one")
}
英文:

I'm not 100% sure I understand the question, but looking at the code you've written, this is how I would get resolve the cannot range issue. This is going to deadlock, because not everything is defined...but ranging isn't an issue or shouldn't be. Also the doStuff code, should signal when the channel should be closed, maybe passed in a wait group, keep track with a counter, etc.

package main

import (
	&quot;fmt&quot;
	&quot;log&quot;
)

// One ...
type One struct{}

// Two ...
type Two struct{}

func doStuff(*interface{}) {}

func myFunc(input string) {
	var myChan interface{}
	switch input {
	case &quot;one&quot;:
		myChan = make(chan One)
	case &quot;two&quot;:
		myChan = make(chan Two)
	}
    // might have to move this line of code into the switch block below...
    // see commented example
	go doStuff(&amp;myChan)

	switch myChan.(type) {
	case chan One:
        // in this way you&#39;re not passing an interface{} but a chan or type One or Two
        // go doStuff(&amp;myChan.(chan One))
		for item := range myChan.(chan One) {
			fmt.Println(item)
		}
	case chan Two:
        // go doStuff(&amp;myChan.(chan One))
		for item := range myChan.(chan Two) {
			fmt.Println(item)
		}
	default:
		log.Fatalln(&quot;Unknown type entered&quot;)
	}

}

func main() {
	myFunc(&quot;one&quot;)
}

huangapple
  • 本文由 发表于 2017年5月26日 21:30:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/44202925.html
匿名

发表评论

匿名网友

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

确定