【golang】channel讲解

1.什么是channel

channel的中文意思就是通道。在go中channel主要是用于协程之间的通信

channel可以在同一时间保证只有一个携程在操作,从而避免了数据的竞争,实现的同步操作。

2.channel使用

1.在go中,channel需要使用make函数进行内存分配。可以使用make函数,指定缓冲区的大小。

ch := make(chan int,6)

如果不指定缓冲区,则成为无缓冲区通道。该通道只有sender和receiver都准备好时,才能进行通信。

例如:

func pump(ch chan int)  {
	for i := 1;;i++ {
		ch <- i
	}
}

	ch1 := make(chan int) // 无缓冲通道
	go pump(ch1)

以上程序没有receiver,程序会报错。因为通道是没有缓冲区的。当sender发送一个数据的时候,必须有receiver接收数据,这样sender才能继续发送数据。类似于生产者->消费者问题

func pump(ch chan int)  {
	for i := 1;;i++ {
		ch <- i
	}
}

	ch1 := make(chan int) // 无缓冲通道
	go pump(ch1)
	fmt.Println(<-ch1) // 这里只接收的到发送的第一个数据1。

2.发送、接收数据

根据 <- 的流向,来判断是向通道发送数据,还是读取通道中的数据

	ch  := make(chan int,1)
	ch <- 10 // 向ch通道发送数据
	ch  = make(chan int,1)
	ch <- 10
	x := <- ch // 读取ch通道中的数据,并复制给x变量。

注意:
不能像已经满了的通道发送数据,否则会造成阻塞。

	ch  = make(chan int,2)
	ch <- 10
	ch <- 20
	ch <- 30 // 通道缓冲区大小为2,已满,不能再发送数据

输出
在这里插入图片描述
该错误告诉我们,所有的线程都已经休眠。则没有一个线程在运行,发生死锁。

3.关闭通道

close(ch) // 使用该方法关闭通道

只有发送者可以关闭通道。

4.读取通道中的数据

for range 可以读取通道中的数据,直到通道关闭

for range

例子:

	for v := range ch1 {
		fmt.Printf("%v",v)
	}

3.单通道

顾名思义,就是单向的通道,也就是只能接受或者发送的通道。

1.只能接收

var ch <- chan int

2.只能发送

var ch chan <- int

4. select

不同于switch,select只能用于io操作,一般配合channel使用。

例子:

		select {
			case msg1 := <-c1:
				fmt.Println("c1 received:",msg1)
			case msg2 := <-c2:
				fmt.Println("c2 received",msg2)
			default:
				fmt.Println("No data received")
		}

以上例子中,只要一个通道里有数据,就会执行case。

如果没有匹配的case,且没有default语句。那么select会阻塞,直到某一case可以执行

与switch的主要区别:

switch的case是顺序匹配执行的。而select是随机执行的。

select中表达式必须是和通道有关的操作。

------------ -------------- 补充-----------------------------------------------------------

5.关闭通道

目前是使用close方法来关闭通道。但是需要注意:

1.在关闭通道的前提下,如果通道中数据,那么返回的是true

	ch := make(chan string,5)
	go func() {
		ch <- "a"
		ch <- "b"
		ch <- "c"
		ch <- "d"
		ch <- "e"
	}()
	time.Sleep(time.Second*10)
	close(ch) // 关闭通道
	v,ok := <-ch
	fmt.Printf("%s,ok=%t\n",v,ok) // v = “a”,ok = true

把上面中的数据读取完毕,返回的是false

	ch := make(chan string,5)
	go func() {
		ch <- "a"
		ch <- "b"
		ch <- "c"
		ch <- "d"
		ch <- "e"
	}()
	time.Sleep(time.Second*10)
	close(ch) // 关闭通道
		for i := 0; i < 5; i++ {
		v,ok := <-ch
		fmt.Printf("%s,ok=%t\n",v,ok)
	}
	v,ok := <-ch
	fmt.Printf("%s,ok=%t\n",v,ok)

运行结果
在这里插入图片描述
目前来看,关闭的通道,在无数据的情况下,会返回false。否则是true。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值