channel通道
package main
import "fmt"
//15
func main() {
/*
channel
*/
var a chan int
fmt.Printf("%T,%v\n",a,a) //chan int,<nil>
if a == nil {
fmt.Println("channel是nil的,不能使用,需要先创建通道")
a = make(chan int)
fmt.Println(a) //0xc00008c060
}
test1(a)
var ch1 chan bool
ch1 = make(chan bool)
go func() {
for i := 0; i < 10; i++ {
fmt.Println("子goroutine:",i)
}
//循环结束,向通道中写数据
ch1 <- true
fmt.Println("结束。。。") //结束。。。
}()
//写之前读阻塞,读之前写阻塞
data := <- ch1
fmt.Println("main data --->",data) //main data ---> true
fmt.Println("main over") //main over
}
func test1(ch chan int){
fmt.Printf("%T,%v\n",ch,ch) //chan int,0xc000100060
}
关闭通道和通道上范围循环
package main
import (
"fmt"
"time"
)
//16
func main() {
/*
关闭通道:close(ch)
子groutine,写出10个数据
每写一个,阻塞一次,主goroutine读取一次,解除阻塞
主goroutine,读取数据
每次读取数据,阻塞一次,子goroutine,写出一个,解除阻塞
*/
ch1 := make(chan int)
go sendData(ch1)
//读取通道的数据
for{
time.Sleep(1 * time.Second)
v,ok := <- ch1
if !ok {
fmt.Println("已经读取了所有数据",v,ok)
break
}
fmt.Println("读取的数据:",v,ok)
}
fmt.Println("main over")
}
func sendData(ch1 chan int) {
//发送方
for i := 0; i < 10; i++ {
ch1 <- i
}
close(ch1)
}
package main
import (
"fmt"
)
//17
func main() {
/*
通过range访问通道
*/
ch1 := make(chan int)
go sendData2(ch1)
//range来访问通道
for v := range ch1 {
fmt.Println("读取数据:",v)
}
fmt.Println("main over")
}
func sendData2(ch1 chan int) {
//发送方
for i := 0; i < 10; i++ {
ch1 <- i
}
close(ch1) //通知对方通道关闭
}
缓冲通道
package main
import (
"fmt"
"strconv"
)
//18
func main() {
/*
非缓冲通道:make(chan T)
一次发送,一次接受,都是阻塞的
缓冲通道:make(chan T,capacity)
发送:缓冲区的数据满了,才会阻塞
接收:缓冲区的数据空了,才会阻塞
*/
ch1 := make(chan int)
fmt.Println(len(ch1), cap(ch1)) //0 0
ch2 := make(chan int, 5)
fmt.Println(len(ch2), cap(ch2)) //0 5
ch2 <- 100
fmt.Println(len(ch2), cap(ch2)) //1 5
ch2 <- 100
ch2 <- 200
ch2 <- 300
ch2 <- 400
fmt.Println(len(ch2), cap(ch2)) //5 5
// ch2 <- 600 //fatal error: all goroutines are asleep - deadlock!
fmt.Println("-------------")
ch3 := make(chan string, 4)
go sendData3(ch3)
for{
v,ok := <-ch3
if !ok {
fmt.Println("读完了..",ok)
break
}
fmt.Println("\t读取的数据是:",v)
}
fmt.Println("main over...")
}
func sendData3(ch chan string){
for i := 0; i < 10; i++ {
ch <- "数据" + strconv.Itoa(i)
fmt.Println("子goroutine中写出第 %d 个数据\n",i)
}
close(ch)
}
定向通道
package main
import "fmt"
//19
func main() {
/*
双向通道
chan T
chan <- data,发送数据,写出
data <- chan,获取数据,读取
单向:定向
chan <- T,只支持写操作
<- chan T,只读
*/
ch1 := make(chan string)
done := make(chan bool)
go sendData4(ch1, done)
data := <- ch1
fmt.Println("子goroutine传来:",data) //子goroutine传来: isuntong
ch1 <- "isuntong2"
<- done //不通知不要结束
fmt.Println("main over...")
}
func sendData4(ch1 chan string, done chan bool) {
ch1 <- "isuntong"
data := <- ch1
fmt.Println("main goroutine传来:",data)
done <- true
}
package main
import "fmt"
//20
func main() {
/*
单向:定向
chan <- T,只支持写操作
<- chan T,只读
用作默写函数保护
函数内部对于ch1只能读,不能写,所以可以保护安全
创建双向channel,在某些函数中限定只读只写,作为保护。
*/
ch1 := make(chan int) //双向,读写
//ch2 := make(chan <- int) //单向,只能写
//ch3 := make(<- chan int) //单向,只能读
// ch2 <- 1000
// data := <-ch2 //invalid operation: <-ch2 (receive from send-only type chan<- int)
// data := <- ch3
// ch3 <- 2000 //invalid operation: ch3 <- 2000 (send to receive-only type <-chan int)
// fmt.Println(data)
go fun3(ch1) //可读可写
// fun3(ch2)
data2 := <- ch1
fmt.Println("fun3函数写出的数据是:",data2) //fun3函数写出的数据是: 100
}
//该函数,只能操作只写的通道
func fun3(ch chan <- int) {
ch <- 100
fmt.Println("fun3函数结束") //fun3函数结束
}
func fun4(ch <- chan int) {
fmt.Println("fun3函数结束") //fun3函数结束
}
time包中的通道相关函数
package main
import (
"fmt"
"time"
)
//21
func main() {
/*
1. func NewTimer(d Duration) *Timer
创建一个计数器,d时间以后触发
2. func After(d Duration) <- chan Time
返回一个通道,存储的是d时间间隔之后的当前时间
*/
timer := time.NewTimer(3 * time.Second)
fmt.Printf("%T\n",timer) //*time.Timer
fmt.Println(time.Now()) //2020-03-26 19:29:30.612334 +0800 CST m=+0.000112607
//此处等待channel中的数据,会阻塞3秒
ch2 := timer.C
fmt.Println(<-ch2) //2020-03-26 19:29:33.614302 +0800 CST m=+3.002032115
//新建一个计数器
timer2 := time.NewTimer(5 * time.Second)
//开始goroutine,来处理触发后的事件
go func() {
<- timer2.C
fmt.Println("Timer2结束")
}()
time.Sleep(3 * time.Second)
flag := timer2.Stop() //停止定时
if flag {
fmt.Println("Timer2停止了")
}
//After(d Duration)
ch := time.After(3 * time.Second)
fmt.Printf("%T\n",ch) //<-chan time.Time
fmt.Println(time.Now()) //2020-03-26 19:40:21.089133 +0800 CST m=+6.004003279
timer3 := <-ch
fmt.Println(timer3) //2020-03-26 19:40:24.091121 +0800 CST m=+9.005942476
}
select语句
package main
import (
"fmt"
"time"
)
//22
func main() {
/*
分支语句:if、switch、select
select类似于switch语句
但是select语句会随机执行一个可运行的case
如果没有case可以执行,要看是否有default,如果有就执行default,否则就进入阻塞,直到有case可以运行
*/
ch1 := make(chan int)
ch2 := make(chan int)
go func() {
time.Sleep(3 * time.Second)
ch1 <- 100
}()
go func() {
time.Sleep(3 * time.Second)
ch2 <- 200
}()
select {
case num1 := <- ch1:
fmt.Println("ch1中获得数据是:", num1)
case num2,ok := <-ch2:
if ok{
fmt.Println("ch2中获得的数据是:",num2)
}else {
fmt.Println("ch2通道已关闭")
}
default:
fmt.Println("default语句。。。")
}
fmt.Println("main over...")
}
CSP并发模型
网友评论