了解channel通道
用于 协程(线程间的通信)
一个通道发送和接收数据,默认是 阻塞
声明通道
使用 make 声明通道
使用 var 定义 通道后,在使用make创建通道
不要通过共享内存实现通信,要通过通信实现共享内存
package main
import "fmt"
func main () {
channel01 := make (chan int )
var channel02 chan bool
channel02 = make (chan bool )
go func () {
for i := 0 ; i < 10 ; i++ {
fmt.Println("goroutine" )
}
channel01 <- 10
channel02 <- true
}()
channelData1 := <-channel01
channelData2 := <-channel02
fmt.Println("获取通道1的数据:" , channelData1)
fmt.Println("获取通道2的数据:" , channelData2)
}
channel死锁 场景
创建了通道 ,没有写入数据 【死锁】
创建了通道,写入数据,没人接收 【死锁】
两个通道相互依赖 【死锁】 channelA <==> channelB
通道关闭
package main
import (
"fmt"
"time"
)
func closeChannelFunc (ch chan int ) {
for i := 0 ; i < 10 ; i++ {
ch <- i
}
close (ch)
}
func main () {
closeCh := make (chan int )
go closeChannelFunc(closeCh)
for {
time.Sleep(time.Second)
data, ok := <-closeCh
if ok == false {
fmt.Println("通道已经读取完毕!" , ok)
break
}
fmt.Println("正在读取通道中的数据:" , data)
}
}
for 遍历通道
package main
import (
"fmt"
"time"
)
func addDataChainFunc (ch chan int ) {
for i := 0 ; i < 10 ; i++ {
ch <- i
time.Sleep(time.Second)
}
close (ch)
}
func main () {
chan02 := make (chan int )
go addDataChainFunc(chan02)
for data := range chan02 {
fmt.Println("for range 遍历通道数据" , data)
}
}
缓冲通道
遵循:先进先出规则
缓冲通道: 通道又一个参数定义缓冲去,发送数据直到缓冲区填满位置,才会被接受。 只有缓冲区清空才会阻塞
非缓冲通道: chan 只能存放一个数据,发送和接收都是阻塞。一次发送一次接收
定义: make(chai int , 1) // 默认是:1
package main
import (
"fmt"
"strconv"
"time"
)
func addDataChanFunc (ch chan string ) {
for i := 0 ; i < 10 ; i++ {
ch <- strconv.Itoa(i)
fmt.Println("子Goroutine 放入数据:" , i)
time.Sleep(time.Second)
}
close (ch)
}
func main () {
unbufferedChannel := make (chan int )
fmt.Printf("非缓冲通道:类型:%T 容量:%d 长度:%d \n" , unbufferedChannel, cap (unbufferedChannel), len (unbufferedChannel))
bufferChannel := make (chan string , 5 )
bufferChannel <- "aaa"
fmt.Printf("缓冲通道:类型:%T 容量:%d 长度:%d \n" , bufferChannel, cap (bufferChannel), len (bufferChannel))
bufferChannel <- "bbb"
fmt.Printf("缓冲通道:类型:%T 容量:%d 长度:%d \n" , bufferChannel, cap (bufferChannel), len (bufferChannel))
bufferChannel <- "ccc"
fmt.Printf("缓冲通道:类型:%T 容量:%d 长度:%d \n" , bufferChannel, cap (bufferChannel), len (bufferChannel))
bufferChannel <- "ddd"
fmt.Printf("缓冲通道:类型:%T 容量:%d 长度:%d \n" , bufferChannel, cap (bufferChannel), len (bufferChannel))
bufferChannel <- "eee"
fmt.Printf("缓冲通道:类型:%T 容量:%d 长度:%d \n" , bufferChannel, cap (bufferChannel), len (bufferChannel))
fmt.Println("****************" )
bufferChan := make (chan string , 4 )
go addDataChanFunc(bufferChan)
for data := range bufferChan {
time.Sleep(1 * time.Second)
fmt.Println("main 读取 bufferChan 中的数据:" , data)
}
fmt.Println("Main end" )
}
定向通道
package main
import (
"fmt"
"sync"
)
func writeOnlyChan (ch chan <- int ) {
data := 1
ch <- data
fmt.Println("只写通道:" , data)
wg.Done()
}
func readOnlyChan (ch <-chan int ) int {
data := <-ch
fmt.Println("只读通道:" , data)
wg.Done()
return data
}
var wg sync.WaitGroup
func main () {
readWriteChan := make (chan int , 1 )
readWriteChan <- 1
data := <-readWriteChan
fmt.Println(data)
chan01 := make (chan int )
wg.Add(2 )
go writeOnlyChan(chan01)
go readOnlyChan(chan01)
wg.Wait()
}
Select 和 channel 使用
package main
import (
"fmt"
"time"
)
func main () {
ch1 := make (chan int )
ch2 := make (chan int )
go func () {
time.Sleep(1 * time.Second * 2 )
ch1 <- 1
}()
go func () {
time.Sleep(1 * time.Second * 2 )
ch2 <- 109
}()
select {
case num1 := <-ch1:
fmt.Println("num1:" , num1)
case num2 := <-ch2:
fmt.Println("num2:" , num2)
}
}
Timer定时器和 channel 通道
package main
import (
"fmt"
"time"
)
func main () {
timerObj := time.NewTimer(time.Second * 3 )
fmt.Println(time.Now())
timeChan := timerObj.C
fmt.Println(<-timeChan)
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?