在Golang中,可以使用`select`关键字来访问通道ch1和ch2吗?

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

Is it possible to access channels ch1, ch2 using `select` in Golang?

问题

我正在尝试调试这段代码,但卡在这里。我想要访问ch1和ch2,但发现没有打印任何内容。

package main

import (
	"fmt"
)

type degen struct {
	i, j string
}

func (x degen) CVIO(ch1, ch2 chan string, quit chan int, m, n string) {
	for {
		select {
		case ch1 <- m:
			fmt.Println(x.i)
		case ch2 <- n:
			fmt.Println("ok")
		case <-quit:
			fmt.Println("quit")
			return
		}
	}

}

func main() {
	ch1 := make(chan string)
	ch2 := make(chan string)
	quit := make(chan int)
	x := degen{"goosebump", "ok"}
	go x.CVIO(ch1, ch2, quit, "goosebump", "ok")
}

期望的结果:
它应该打印即将产生的通道数据。

英文:

I was trying to debug this code but am stuck here. I wanted to access ch1, ch2 but found printed nothing.

package main

import (
	&quot;fmt&quot;
)

type degen struct {
	i, j string
}

func (x degen) CVIO(ch1, ch2 chan string, quit chan int, m, n string) {
	for {
		select {
		case ch1 &lt;- m:
			fmt.Println(x.i)
		case ch2 &lt;- n:
			fmt.Println(&quot;ok&quot;)
		case &lt;-quit:
			fmt.Println(&quot;quit&quot;)
			return
		}
	}

}

func main() {
	ch1 := make(chan string)
	ch2 := make(chan string)
	quit := make(chan int)
	x := degen{&quot;goosebump&quot;, &quot;ok&quot;}
	go x.CVIO(ch1, ch2, quit, &quot;goosebump&quot;, &quot;ok&quot;)
}

Desired:
It should print the channel data as to be produced.

答案1

得分: 3

你的代码的预期功能并不是很清楚:

  • main() 函数在结束时没有等待 go 协程退出(循环可能根本不会运行)。
  • select 语句中,发送操作无法进行,因为没有接收者(参考 规范 - "如果容量为零或不存在,则通道是无缓冲的,只有在发送方和接收方都准备好时通信才会成功。")。
  • 没有向 quit 通道发送任何内容。

我怀疑以下代码(playground)可能会实现你的预期功能。

package main

import (
	"fmt"
	"sync"
)

type degen struct {
	i, j string
}

func (x degen) CVIO(ch1, ch2 chan string, quit chan int, m, n string) {
	for {
		select {
		case ch1 <- m:
			fmt.Println(x.i)
		case ch2 <- n:
			fmt.Println("ok")
		case <-quit:
			fmt.Println("quit")
			return
		}
	}

}

func main() {
	ch1 := make(chan string)
	ch2 := make(chan string)
	quit := make(chan int)
	x := degen{"goosebump", "ok"}
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		x.CVIO(ch1, ch2, quit, "goosebump", "ok")
		wg.Done()
	}()

	<-ch1 // 从 CH1 接收(允许 go 协程中的 "ch1 <- m" 继续执行)
	<-ch2 // 从 CH2 接收(允许 go 协程中的 "ch2 <- n" 继续执行)

	quit <- 1
	wg.Wait() // 等待 CVIO 结束(由于上述发送操作,它应该会结束)
}

希望对你有帮助!

英文:

Its not really clear what you expect your code to do:

  • main() ends without waiting for the go routine to exit (its quite possible it the loop will not run at all).
  • in the select the sends will not proceed because there is no receiver (spec - "if the capacity is zero or absent, the channel is unbuffered and communication succeeds only when both a sender and receiver are ready.").
  • Nothing is sent to the quit channel.

I suspect that the following (playground) might do what you were expecting.

package main

import (
	&quot;fmt&quot;
	&quot;sync&quot;
)

type degen struct {
	i, j string
}

func (x degen) CVIO(ch1, ch2 chan string, quit chan int, m, n string) {
	for {
		select {
		case ch1 &lt;- m:
			fmt.Println(x.i)
		case ch2 &lt;- n:
			fmt.Println(&quot;ok&quot;)
		case &lt;-quit:
			fmt.Println(&quot;quit&quot;)
			return
		}
	}

}

func main() {
	ch1 := make(chan string)
	ch2 := make(chan string)
	quit := make(chan int)
	x := degen{&quot;goosebump&quot;, &quot;ok&quot;}
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		x.CVIO(ch1, ch2, quit, &quot;goosebump&quot;, &quot;ok&quot;)
		wg.Done()
	}()

	&lt;-ch1 // Receive from CH1 (allowing &quot;ch1 &lt;- m&quot; in go routine to proceed)
	&lt;-ch2 // Receive from CH2 (allowing &quot;ch2 &lt;- n&quot; in go routine to proceed)

	quit &lt;- 1
	wg.Wait() // Wait for CVIO to end (which it should do due to above send)
}

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

发表评论

匿名网友

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

确定