goroutine
Go语言中,没有多线程机制,取而代之的是goroutine。goroutine的概念类似于线程, 但 goroutine 由 Go 程序运行时的调度和管理,Go 程序会智能地将 goroutine 中的任务合理地分配给每个 CPU。
具体的调试模式采用了GPM模式,G为goroutine,P为逻辑处理器,M为物理处理器
创建goroutine
程序在启用时,会默认创建一个goroutine。当我们需要主动去创建一个goroutine时,只需要通过以下方式:
go 函数名( 参数列表 )
# 列如
func main() {
go func() {
for i :=0; ; i++{
log.Printf("GO!GO!GO!,%d", i)
time.Sleep(time.Second)
}
}()
for i :=0; ; i++{
log.Printf("TO!TO!TO!,%d", i)
time.Sleep(time.Second)
}
}
以上匿名函数中的循环与main函数中的循环会并发执行,无先后顺序。 需要注意的是当main函数执行完时,新建的goroutine函数体也会中断?
管道channel
Go 语言中的管道(channel)是一种特殊的类型。在任何时候,同时只能有一个 goroutine 访问管道进行发送和获取数据。这使得goroutine 间通过管道就可以通信。管道像一个传送带或者队列,总是遵循先入先出的规则,保证收发数据的顺序。
是引用类型,需要使用 make 进行创建,格式如下:
通道实例 := make(chan 数据类型)
# 列如
x := true
c := make(chan bool) //创建一个无缓冲的bool型Channel
go func() {
c <- x //向一个Channel发送一个值
}()
x =
//从Channel c接收一个值并将其存储到x中
x, ok = <- c //从Channel接收一个值,如果channel关闭了或没有数据,那么ok将被置为false
x := true
c := make(chan bool) //创建一个无缓冲的bool型Channel
c <- x //向一个Channel发送一个值
x = <- c //从Channel c接收一个值并将其存储到x中
goroutine间通信
c := make(chan int)
go func() {
c <- 1
c <- 2
}()
// 循环读取
for d := range c {
fmt.Println(d)
if d >= 1 {
break
}
}
// 单条读取
d, ok := <-c
fmt.Println(d)
fmt.Println(ok)
定向通信管道
管道的操作权限还可以进行发送与接收的拆分
ch := make(chan int)
// 声明一个只能发送的通道类型, 并赋值为ch
var sendCh chan<- int = ch
//声明一个只能接收的通道类型, 并赋值为ch
var recvCh <-chan int = ch
创建带缓冲通道
通道实例 := make(chan 通道类型, 缓冲大小)