Go学习:channel

概念

在这里插入图片描述

goroutine与goroutine之间的双向通道就是channel

语法

定义

package main

import "fmt"

func chanDemmo() {
	c := make(chan int)
	c <- 1
	c <- 2
	n := <-c
	fmt.Println(n)
}

func main() {
	chanDemmo()
}

在这里插入图片描述
运行程序,会出现死锁;channel是goroutine与goroutine之间的交互,如果没有goroutine就会出现死锁

package main

import (
	"fmt"
	"time"
)

func chanDemmo() {
	c := make(chan int)
	go func() {
		for {
			n := <-c
			fmt.Println(n)
		}
	}()
	c <- 1
	c <- 2
	time.Sleep(time.Millisecond)
}

func main() {
	chanDemmo()
}

在这里插入图片描述
加一个sleep是为了把所有的内容都打印出来

chan作为参数

package main

import (
	"fmt"
	"time"
)

func chanDemmo() {
	c := make(chan int)
	go worker(c)
	c <- 1
	c <- 2
	time.Sleep(time.Millisecond)
}

func worker(c chan int) {
	for {
		n := <-c
		fmt.Println(n)
	}
}

func main() {
	chanDemmo()
}

在这里插入图片描述

package main

import (
	"fmt"
	"time"
)

func chanDemmo() {
	var channels [10]chan int
	for i := 0; i < 10; i++ {
		channels[i] = make(chan int)
		go worker(i, channels[i])
	}
	for i := 0; i < 10; i++ {
		channels[i] <- i
	}
	time.Sleep(time.Millisecond)
}

func worker(id int, c chan int) {
	for {
		fmt.Printf("Worker %d received %d\n", id, <-c)
	}
}

func main() {
	chanDemmo()
}

在这里插入图片描述

chan作为返回值

返回可收可发的chan
package main

import (
	"fmt"
	"time"
)

func createChan() chan int {
	c:=make(chan int)
	return c
}

func chanDemmo() {
	var channels [10]chan int
	for i := 0; i < 10; i++ {
		channels[i] = createChan()
		go worker(i, channels[i])
	}
	for i := 0; i < 10; i++ {
		channels[i] <- i
	}
	time.Sleep(time.Millisecond)
}

func worker(id int, c chan int) {
	for {
		fmt.Printf("Worker %d received %d\n", id, <-c)
	}
}

func main() {
	chanDemmo()
}

在这里插入图片描述

返回具体用途的chan
package main

import (
	"fmt"
	"time"
)

func createChan() chan int {
	c := make(chan int)
	return c
}
func createSendChan() chan<- int {
	c := make(chan int)
	return c
}

func chanDemmo() {
	var channels [10]chan<- int
	for i := 0; i < 10; i++ {
		channels[i] = createSendChan()
		// go worker(i, channels[i])
	}
	for i := 0; i < 10; i++ {
		channels[i] <- i
	}
	time.Sleep(time.Millisecond)
}

func worker(id int, c chan int) {
	for {
		fmt.Printf("Worker %d received %d\n", id, <-c)
	}
}

func main() {
	chanDemmo()
}

我们再createSendChan函数里面规定了返回的chan只能取发数据,如果我们用返回的chan收数据程序会编译不通过

bufferedChan

再最开始的例子里面说,如果没有goroutine来接收,会出现死锁,但是我们可以再创建chan的时候设置一个缓冲区,这样的话,发送内容的时候就会发送到缓冲区里面,只有超出了缓冲区大小时才会出现死锁

不超过缓冲区
package main

func main() {
	bufferedChan()
}

func bufferedChan() {
	c:=make(chan int,3)
	c <- 1
	c <- 2
	c <- 3
}

在这里插入图片描述

超过缓冲区
package main

func main() {
	//chanDemmo()
	bufferedChan()
}

func bufferedChan() {
	c:=make(chan int,3)
	c <- 1
	c <- 2
	c <- 3
	c <- 3
}

在这里插入图片描述

接收bufferedChan数据
package main

import (
	"fmt"
	"time"
)

func worker(id int, c chan int) {
	for {
		fmt.Printf("Worker %d received %d\n", id, <-c)
	}
}

func main() {
	bufferedChan()
}

func bufferedChan() {
	c:=make(chan int,3)
	go worker(0,c)
	c <- 1
	c <- 2
	c <- 3
	c <- 4
	time.Sleep(time.Millisecond)
}

在这里插入图片描述

close chan

判断是否还有数据
package main

import (
	"fmt"
	"time"
)

func main() {
	bufferedChan()
}

func bufferedChan() {
	c:=make(chan int,3)
	go workerClose(0,c)
	c <- 1
	c <- 2
	c <- 3
	c <- 4
	close(c)
	time.Sleep(time.Millisecond)
}

func workerClose(id int, c chan int) {
	for {
		i,ok := <-c
		if !ok {
			break
		}
		fmt.Printf("Worker %d received %d\n", id, i)
	}
}

在这里插入图片描述

使用range
package main

import (
	"fmt"
	"time"
)

func main() {
	bufferedChan()
}

func bufferedChan() {
	c:=make(chan int,3)
	go workerClose(0,c)
	c <- 1
	c <- 2
	c <- 3
	c <- 4
	close(c)
	time.Sleep(time.Millisecond)
}

func workerClose(id int, c chan int) {
	for i:= range c{

		fmt.Printf("Worker %d received %d\n", id, i)
	}
}

在这里插入图片描述
close一定要由发送方去close;如果不进行close的话,程序就会一直收数据直至结束!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.番茄炒蛋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值