加载中...

Channel

什么是chanel

用来连接并发的goroutine的,一个goroutine通过chanel向另一个goroutine发送消息,对应的goroutine通过channel来接受消息。

如何定义channel

var <变量名称> chan <数据类型>

var intChan chan int
var strChan chan string
var strChan chan *string
var objChan chan struct{}

channel是引用类型。
需要使用make方法来实例化

make(chan int)   # 不带缓存(buffer)的channel
make(chan int,3) # 带缓存(buffer)的channel
make(chan *string)
make(chan *map[string]struct)

示例

func TestDefChannel(t *testing.T){
	var intCh chan int
	fmt.Println("intChan",intCh) // <nil>
	intCh = make(chan int,1)
	fmt.Println("intCh",intCh) // 0xc**** 
}

Channel特性

1、Channel本质是一个队列,先进先出
2、Channel本身是线程安全的,多个goroutine去操作它,是安全的
3、Channel是数据类型敏感的

示例

func TestDefChannel(t *testing.T){
	intCh := make(chan int,1)
	fmt.Println("intCh",intCh)

	intCh <- 3

	out := <- intCh

	fmt.Println(out)
}

Channel的操作

添加数据
intChan <- 8
取出数据
out <- intChan

func main() {
	// 创建一个不带buffer缓存的channel
	// 该channel用于传递int类型的数据
	IntChan := make(chan int)
	workerCount := 10
	for i := 0; i < workerCount; i++ {
		go func(i int) {
			IntChan <- i
		}(i)
	}
	for j := 0; j < workerCount; j++ {
		go func(j int) {
			// 从IntChan中接收数据
			num := <-IntChan
			// 打印接收到的数据
			fmt.Printf("Received: %d\n", num)
		}(j)
	}
	// 等待所有goroutine完成
	time.Sleep(1 * time.Second)
}
Received: 0
Received: 4
Received: 1
Received: 2
Received: 3
Received: 9
Received: 5
Received: 6
Received: 7
Received: 8

对于没有缓冲区的channel而言,如果没有channel没有出,它是无法写入数据的。

遍历

Channel 只能通过for... range遍历
如果channel没有关闭,也没有数据进入的话,那么就会报错,死锁。
关闭的Channel无法再装入数据,可以继续取数据,直到channel为空

intCh := make(chan int ,10)
intCh <- 1
intCh <- 1
intCh <- 1
intCh <- 1
intCh <- 1
intCh <- 1

for i :=range intCh{
	fmt.Println(i)
}
1
1
1
1
1
1
fatal error: all goroutines are asleep - deadlock!

一定要记得关闭不使用的channel

intCh := make(chan int ,10)
intCh <- 1
intCh <- 1
intCh <- 1
intCh <- 1
intCh <- 1
intCh <- 1
close(intCh)

for i :=range intCh{
	fmt.Println(i)
}

或者

func main() {
	intCh := make(chan int, 10)
	intCh <- 1
	intCh <- 1
	intCh <- 1
	intCh <- 1
	intCh <- 1
	intCh <- 1
	close(intCh)

	for {
		if data, ok := <-intCh; ok {
			fmt.Println(data)
		} else {
			fmt.Println("Channel has been closed")
			break
		}
	}
}

posted @ 2024-07-01 22:07  Ykubernetes  阅读(12)  评论(0编辑  收藏  举报