Go 语言 channel通道的基础知识
通道(channel)就是一个管道,可以想象成Go 协程之间通信的管道,他是一种队列的数据结构,遵循先进先出的规则
通道的声明
每一个通道只能传递一种数据结构的数据,在我们声明的时候,就要指定管道的类型,chan Type 表示Type类型的通道,通道的零值为nil
var channel_name chan channel_type
func channel() {
//声明了一个类型为string的通道,值为nil
var channel chan string
channel =make(chan string)
fmt.Println(channel)
//简单的声明方式
ch :=make(chan string)
}
管道初始化以及使用
声明完通道之后,其值为nil,我们不能直接使用,必须先使用make函数对通道进行初始化操作
package main
import (
"fmt"
"time"
)
func channel() {
//声明了一个类型为string的通道,值为nil
var channel chan string
fmt.Println(channel)
}
func PrintChan(c chan string) {
c <- "第七魂技 - 武魂真身"
}
func ChanTest() {
/**
发送数据 channel_name <- data
接收数据 value :=<-channel_name
*/
//创建一个通道
ch := make(chan string)
fmt.Println("第一魂技。。。")
//开启协程
go PrintChan(ch)
//从通道中获取数据
res := <-ch
fmt.Println(res)
fmt.Println("第九魂技。。。")
//关闭通道
close(ch)
_, ok := <-ch
//检查通道是否关闭
fmt.Println(ok)
/**
无缓冲通道
c :=make(chan int)
c :=make(chan int,0)
缓冲通道
c :=make(chan int ,3)//数值
*/
c := make(chan int)
go func() {
fmt.Println("send 1")
c <- 1
}()
go func() {
n := <-c
fmt.Println("receive", n)
}()
time.Sleep(1 * time.Second)
}
/**
只读通道 <-than
只写通道 chan <-
*/
type Sender = chan<- string
type Receiver = <-chan string
func ChanTest01() {
//创建一个双向通道
ch := make(chan string)
go func() {
var sender Sender = ch
fmt.Println("即将学习。。。")
sender <- "第二魂技-床绕"
}()
go func() {
var receiver Receiver = ch
message := <-receiver
fmt.Println("开始学习:", message)
}()
time.Sleep(1 * time.Second)
}
func RangeChan() {
//遍历通道 for range
var channel = make(chan int, 5)
go LoopPrint(channel)
for v := range channel {
fmt.Println(v)
}
channel1 := make(chan bool, 1)
var x int
for i := 0; i < 1000; i++ {
go increment(channel1, &x)
}
time.Sleep(1 * time.Second)
fmt.Println("x=", x)
}
func LoopPrint(c chan int) {
for i := 0; i < 10; i++ {
c <- i
}
close(c)
}
func increment(ch chan bool, x *int) {
ch <- true
//不是原子操作,避免多协程进行操作;使用容量为1的通道,达到锁的效果
*x = *x + 1
<-ch
}
func funcReceiver(c chan bool) {
fmt.Println(<-c)
}
func main() {
RangeChan()
ch := make(chan bool)
//1.开启一个协程,再往管道写入数据,这样就不会产生死锁 go funcReceiver(ch)
//2. 把无缓冲通道改为有缓冲通道 ch := make(chan bool, 1)
//go funcReceiver(ch)
//往通道里写数据
ch <- true
//通道里读数据 ---看上去没啥问题,其实会产生死锁 fatal error: all goroutines are asleep - deadlock!
fmt.Println(<-ch)
}