惊风破浪的博客
PHP
MySQL
Redis
Linux
算法与设计模式
杂项
Golang
登录
学习Go协程和管道
1个月前 ⋅
0
##### 协程 `协程是并行的,是一种轻量级的线程` ```go package main import "fmt" func f(from string) { for i := 0; i < 3; i++ { fmt.Println(from, ":", i) } } func main() { //同步 f("direct") //协程调用这个函数 go f("goroutine") //匿名函数启动go协程 go func(msg string) { fmt.Println(msg) }("going") //两个 Go 协程在独立的 Go 协程中异步(asynchronously)运行 fmt.Scanln() fmt.Println("done") } ``` #### 协程通道中读取数据 ``` package main import "fmt" func main() { //创建一个新当通道 message := make(chan string) //使用channel <-语法 发送(send)一个新的值到通道中 //这里新的协程发送ping到上面创建的 go func() { message <- "ping" }() //<-channel 从通道中接收值 msg :=<-message fmt.Println(msg) } ``` #### 通道缓冲 Buffering ```go package main import "fmt" func main() { //创建一个字符串通道,最多运行缓存2个值 messages :=make(chan string,2) messages <- "buffer" messages <- "channels" //接收 fmt.Println(<-messages) fmt.Println(<-messages) } ``` #### 通道同步 ```go package main import ( "fmt" "time" ) //go协程的函数。done通道 func worker(done chan bool) { fmt.Println("worker....") time.Sleep(time.Second) fmt.Println("done") done <- true } func main() { //运行worker协程,并给予通知的通道 done := make(chan bool,1) go worker(done) //接收到通道中worker发出通知前一直阻塞 <-done } ``` #### 通道方向 ```go package main import "fmt" // `ping` 函数定义了一个只允许发送数据的通道。尝试使用这个通 func ping(pings chan<-string,msg string) { pings <- msg } // `pong` 函数定义了一个只允许接收来自通道(ping)的数据。 func pong(pings <-chan string, pongs chan<- string) { msg := <-pings pongs <- msg } func main() { pings := make(chan string, 1) pongs := make(chan string, 1) ping(pings, "passed message") pong(pings, pongs) fmt.Println(<-pongs) } ``` #### 通道选择器 ```go package main import ( "fmt" "time" ) func main() { c1 :=make(chan string) c2 :=make(chan string) //go 协程中堵塞PRC go func() { time.Sleep(time.Second * 1) c1 <- "one" }() go func() { time.Sleep(time.Second * 2) c2 <- "two" }() //使用select关键词同时等待这两个值 for i :=0;i<2;i++ { select { case msg1:=<-c1: fmt.Println("received",msg1) case msg2 :=<-c2: fmt.Println("received",msg2) } } } ``` #### 协程超时,堵塞,关闭 `带缓冲区的通道允许发送端的数据发送和接收端的数据获取处于异步状态,就是说发送端发送的数据可以放在缓冲区里面,可以等待接收端去获取数据,而不是立刻需要接收端去获取数据。` ```go package main import ( "fmt" "time" ) func main() { //外部调用 并在2秒后 c1 := make(chan string, 1) go func() { time.Sleep(time.Second * 2) c1 <- "result 1" //协程发送 }() //超时操作 select { case res := <-c1: fmt.Println(res) case <-time.After(time.Second * 2): fmt.Println("timeout 1") } mssage :=make(chan string) //非堵塞接收例子 select { case msg :=<-mssage: fmt.Println("received message",msg) default: fmt.Println("no message received") } //协程关闭 jobs :=make(chan int,5) done := make(chan bool) go func() { for { j,more :=<-jobs if more { fmt.Println("received job",j) }else{ fmt.Println("received all jobs") done <-true return } } }() //3任务发送到函数中,然后关闭 for j:=1;j<=3;j++{ jobs <-j fmt.Println("sent job",j) } close(jobs) fmt.Println("sent all job") } ``` #### 协程遍历 ```go package main import "fmt" func main() { queue :=make(chan string,2) queue <-"one" queue <- "two" close(queue) //遍历协程 //如果我们没有 `close` 它,我们将在这个循环中 // 继续阻塞执行,等待接收第三个值 for elem :=range queue{ fmt.Println(elem) } } ```
回复
发布文章
友情链接
Mr.Zhu
Swoole
PHP官网
菜鸟教程
Go语言中文网
implode
数据结构与算法