这是我参与[第五届青训营]的第十二天
goroutine是一个轻量级的执行线程。
可以为匿名函数调用启动一个 go routine。
package main
import (
"fmt"
"time"
)
func f(from string) {
for i := 0; i < 3; i++ {
fmt.Println(from, ":", i)
}
}
func main() {
f("direct")
go f("goroutine")
go func(msg string) {
fmt.Println(msg)
}("going")
time.Sleep(time.Second)
fmt.Println("done")
}
如果我们的两个函数调用在单独的go routine中异步运行。等待完成(更可靠的方法,使用WaitGroup)。
$ go run goroutines.go
direct: 0
direct: 1
direct: 2
goroutine: 0
going
goroutine: 1
goroutine: 2
done
- 频道(Channels)
package main
import "fmt"
func main() {
messages := make(chan string)
go func() { messages <- "ping" }()
msg := <-messages
fmt.Println(msg)
}
通道(channel)是go语言中用于连接并发go routine的通道。
默认情况下发送和接收块,直到发送方和接收方都准备好。此属性允许我们在程序结束时等待"ping" 消息,而无需使用任何其他同步。
- 通道缓冲(Channel BUffering)
package main
import "fmt"
func main() {
messages := make(chan string, 2)
messages <- "buffered"
messages <- "channel"
fmt.Println(<-messages)
fmt.Println(<-messages)
}
默认情况下,通道是无缓冲的,这意味着chan <-如果有相应的 receive( <- chan) 准备好接收发送的值,它们将只接受 sends()。缓冲通道接受有限数量的值,而这些值没有相应的接收器。
这里make有一个字符串通道,最多缓冲2个值
因为通道是缓冲的,可以将这些值发送到通道中而无需相应的并发接收。
- 通道同步(Channel Synchronization)
package main
import (
"fmt"
"time"
)
func worker(done chan bool) {
fmt.Print("working...")
time.Sleep(time.Second)
fmt.Println("done")
done <- true
}
func main() {
done := make(chan bool, 1)
go worker(done)
<-done
}
上面使用的done通道将用于通知另一个go routine。
发送一个值以告知已完成
启动一个 worker goroutine,为其提供通知通道。
- 通道方向(Channel Directions)
package main
import "fmt"
func ping(pings chan<- string, msg string) {
pings <- msg
}
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)
}
使用通道作为函数参数时,可以指定通道是仅用于发送还是接收值。这种特殊性增加了程序的类型安全性。