channel
的创建
go语言中,任意类型前面加上关键字chan
即可声明对应类型的通道,创建通道需要使用make,make也用于map 和slice的创建
创建一个通道
/*刚创建的通道是nil*/
var a chan bool
a = make(chan bool)
使用匿名函数创建一个goroutine
go func() {
for i := 1; i < 10; i++ {
fmt.Println("子goroutine is running....", i)
}
// 往通道中写值
a <- true
fmt.Println("结束....")
}()
按照阻塞的方式读取通道中的值
// 读取的操作是注阻塞的
data := <-a
package main
import "fmt"
func main() {
/*
通道名 channel
*/
/*刚创建的通道是nil*/
var a chan bool
fmt.Printf("%T,%v\n", a, a)
a = make(chan bool)
// 使用匿名函数创建一个`goroutine`
go func() {
for i := 1; i < 10; i++ {
fmt.Println("子goroutine is running....", i)
}
a <- true
fmt.Println("结束....")
}()
fmt.Println("main....over.....")
// 读取的操作是注阻塞的
data := <-a
fmt.Println(data)
fmt.Println("channel demo")
}
通道关闭
package main
import (
"fmt"
"time"
)
func main() {
/*
关闭通道:close(ch)
子goroutine;写10个数据
每写一个,阻塞一次,主goroutine读取一次 解除阻塞
主goroutine 读取数据
每次读取数据,阻塞一次, 子goroutine每次写入一个就解除主阻塞
*/
cha1 := make(chan int)
go sendData1(cha1)
//读取数据.使用for循环需要自己判断是否通道关闭
/* for {
v, ok := <-cha1
if !ok {
fmt.Println("已经读取了所有的数据......", ok)
break
}
fmt.Println("读取的数据....", v)
}
*/
// 使用for range就可以让range自己判断通道啥时候关闭
// cha1关闭的时候,这里range将停止遍历
for v := range cha1 {
fmt.Println("main ..over....", v)
}
//单向 只能写数据,不能读数据
//ch1 := make(chan <- int)
// 单向只能读不能写数
//ch2 := make(<- chan int)
fmt.Println("channel close")
}
func sendData1(cha1 chan int) {
for i := 0; i < 10; i++ {
time.Sleep(1000 * time.Millisecond)
cha1 <- i
}
close(cha1)
}
使用通道进行数据发送的小例子
// 1. 创建goroutine1, 向 ch1中发送1,100个数
// 2. 创建goroutine2, 向 ch2中发送, 1,-1000的平方
// 3. main函数中从ch2将值取出
package main
import (
"fmt"
"sync"
)
// 1. 创建goroutine1, 向 ch1中发送1,100个数
// 2. 创建goroutine2, 向 ch2中发送, 1,-1000的平方
// 3. main函数中从ch2将值取出
var wg1 sync.WaitGroup
func wg1Fun(ch1 chan int) {
defer wg1.Done()
for i := 1; i <= 100; i++ {
ch1 <- i
}
close(ch1)
}
func wg2Fun(ch2 chan int, ch1 chan int) {
defer wg1.Done()
for {
x, ok := <- ch1
if !ok {
break
}
ch2 <- x * x
}
close(ch2)
}
func main() {
var ch1 = make(chan int, 100)
var ch2 = make(chan int, 100)
wg1.Add(2)
go wg1Fun(ch1)
go wg2Fun(ch2, ch1)
wg1.Wait()
for v := range ch2 {
fmt.Println("get ch2 is ", v)
}
}
go语言中,对已经关闭的通道进行取值,能够取到,只不过取到的ok为false
package main
import "fmt"
// 对已经关闭的通道进行取值,能够取到不过ok返回的false
func main() {
ch1 := make(chan bool, 2)
ch1 <- true
ch1 <- true
// 关闭通道
close(ch1)
<- ch1
<- ch1
x, ok := <- ch1
fmt.Println(x, ok)
x, ok = <- ch1
fmt.Println(x, ok)
x, ok = <- ch1
fmt.Println(x, ok)
}