七、《go 并发编程》channel通道

260 阅读1分钟
通道使用语法

理论知识就略过了

发送和接收
package main

import (
	"fmt"
)

var ch1 chan int

func main() {
	// 创建只能传递 int 类型值的通道
	ch1 = make(chan int)
	// chan int 0xc00005e060
	//fmt.Printf("%T %v\n", ch1, ch1)

	// 子 goroutine
	go wirteData()

	// 主 goroutine 读取通道 ch1 当中的数据
	data := <-ch1

	fmt.Println("主 goroutine 从通道 ch1 读取的数据:",data)

}

// 子 goroutine
func wirteData() {
	fmt.Println("子 goroutine 向通道 ch1 写入数据")
	ch1 <- 11111
	fmt.Println("子 goroutine 执行结束。。")
}

执行结果

子 goroutine 向通道 ch1 写入数据
子 goroutine 执行结束。。
主 goroutine 从通道 ch1 读取的数据: 11111
分析

image-20200924174047341

Channel通道在使用的时候,有以下几个注意点:
  • 1.用于goroutine,传递消息的。
  • 2.通道,每个都有相关联的数据类型, nil chan,不能使用,类似于nil map,不能直接存储键值对
  • 3.使用通道传递数据:<- chan <- data,发送数据到通道。向通道中写数据 data <- chan,从通道中获取数据。从通道中读数据
  • 4.阻塞: 发送数据:chan <- data,阻塞的,直到另一条goroutine,读取数据来解除阻塞 读取数据:data <- chan,也是阻塞的。直到另一条goroutine,写出数据解除阻塞。
  • 5.本身channel就是同步的,意味着同一时间,只能有一条goroutine来操作。
关闭通道
package main

import (
	"fmt"
	"time"
)

var ch chan int

func main() {
	ch = make(chan int)
	
	// 子 goroutine 执行
	go send()
	
	// 循环向通道 ch 读取数据
	for value := range ch {
		fmt.Println("主 goroutine 读取通道 ch 的值:",value)
	}
	fmt.Println("运行结束")
}

func send() {
	for i := 1; i < 10; i++ {
		time.Sleep(1 * time.Second)
		fmt.Println("子 goroutine 向通道 ch 写入:",i)
		ch <- i
	}
	fmt.Println("关闭通道 ch ")
	close(ch)
}
关闭运行结果
子 goroutine 向通道 ch 写入: 1
主 goroutine 读取通道 ch 的值: 1
子 goroutine 向通道 ch 写入: 2
主 goroutine 读取通道 ch 的值: 2
子 goroutine 向通道 ch 写入: 3
主 goroutine 读取通道 ch 的值: 3
子 goroutine 向通道 ch 写入: 4
主 goroutine 读取通道 ch 的值: 4
子 goroutine 向通道 ch 写入: 5
主 goroutine 读取通道 ch 的值: 5
子 goroutine 向通道 ch 写入: 6
主 goroutine 读取通道 ch 的值: 6
子 goroutine 向通道 ch 写入: 7
主 goroutine 读取通道 ch 的值: 7
子 goroutine 向通道 ch 写入: 8
主 goroutine 读取通道 ch 的值: 8
子 goroutine 向通道 ch 写入: 9
关闭通道 ch 
主 goroutine 读取通道 ch 的值: 9
运行结束
通道关闭的意义

读和写需要完全对应,如果一直阻塞读,而不往通道去写,必然会造成死锁