概念这里我们不多赘述,直接看实际开发中它的区别。
首先我们看无缓冲通道
package main
import (
"fmt"
"test/channeltest/ano"
"time"
)
// 接收消息函数
func receiveMessage(ch <-chan string) {
msg := <-ch
fmt.Println("接收到消息:", msg)
}
// 发送消息函数
func sendMessage(ch chan<- string, msg string) {
ch <- msg
fmt.Println("发送消息:", msg)
}
func main() {\
// 创建通道
ch := make(chan string)
// 发送消息
sendMessage(ch, "Hello, test!")
// 启动接收消息的 goroutine
go receiveMessage(ch)
// 保持程序运行,等待接收消息
time.Sleep(3 * time.Second)
}
报错:出现死锁
分析原因:
因为是无缓冲通道,他需要有协程去接收它,而在上面的代码中,先执行了发送的代码,接收的代码还没有执行导,也就是没有接收消息的协程,所以会卡死。
将代码换成
go sendMessage(ch, "Hello, test!")
go receiveMessage(ch)
没有问题!
再看有缓冲通道:
package main
import (
"fmt"
"time"
)
// 接收消息函数
func receiveMessage(ch <-chan string) {
msg := <-ch
fmt.Println("接收到消息:", msg)
}
// 发送消息函数
func sendMessage(ch chan<- string, msg string) {
ch <- msg
fmt.Println("发送消息:", msg)
}
func main() {
// 创建通道
ch := make(chan string, 1)
// 启动接收消息的 goroutine
sendMessage(ch, "Hello, test!")
go receiveMessage(ch)
// 发送消息
// 保持程序运行,等待接收消息
time.Sleep(3 * time.Second)
}
运行结果:
可以看出运行是没有问题的。
当有缓冲的channel内无数据继续读会发生什么
func main() {
num := 5
wg := sync.WaitGroup{}
var resch = make(chan int, 100)
for i := 0; i < num; i++ {
wg.Add(1)
go func(params int) {
defer wg.Done()
//defer close(resch)
resch <- job(params)
//fmt.Println(job(params))
}(i)
}
//go func() {
wg.Wait()
//defer close(resch)
//}()
for v := range resch {
fmt.Println(v)
}
//resch <- 1
}
看channel的容量是100,我只向里面发送5条数据,读取后不关闭,死锁
那么向一个关闭的协程写数据会发生什么呢
func main() {
num := 5
wg := sync.WaitGroup{}
var resch = make(chan int, 100)
for i := 0; i < num; i++ {
wg.Add(1)
go func(params int) {
defer wg.Done()
//defer close(resch)
resch <- job(params)
//fmt.Println(job(params))
}(i)
}
go func() {
wg.Wait()
defer close(resch)
}()
for v := range resch {
fmt.Println(v)
}
resch <- 1
}
panic!
向一个关闭的协程取呢?
func main() {
num := 5
wg := sync.WaitGroup{}
var resch = make(chan int, 100)
for i := 0; i < num; i++ {
wg.Add(1)
go func(params int) {
defer wg.Done()
//defer close(resch)
resch <- job(params)
//fmt.Println(job(params))
}(i)
}
go func() {
wg.Wait()
defer close(resch)
}()
for v := range resch {
fmt.Println(v)
}
i:= <- resch
fmt.Println(i)
}
不报错返回channel类型的0值