goroutine(协程),是一种轻量级的线程,平时写的main函数也是运行在goroutine之上的,启动一个新的goroutine格式如下
go 表达式语句//可以是函数或者自定义的方法
值得注意的是,代码次序并不代表goroutine执行次序,尝试注释掉第14行语句,查看运行结果
package main
import (
"fmt"
"time")
func test() {
fmt.Println("hello world")
}
func main() {
go test()
time.Sleep(time.Second) //阻塞主线程一秒,如果注释掉这句话,大概率不会打印执行,因为main函数已经结束
}
channel是一种goroutine之间的通道,可以看作是一座传输数据的桥梁,channel是引用类型。定义如下:
var channel_Name chan T//chan是关键字,T是通道中传输的数据类型
var gochannel chan int//定义了一个叫做gochannel的通道,通道中传输的数据是int类型
用make对channel进行初始化
ch := make(chan T,sizeOfchan)//sizeOfchan指定一个缓冲区大小,也可不指定,缓冲区满channel将堵塞
使用<-来读取和发送
ch <- val//将数据val发送到通道ch中
val := <- ch//从通道读取数据给val赋值//构造单向通道
ch1,ch2ch := make(chan T)
var ch1 chan <- int = ch//只能发送var ch2 chan <- int = ch//只能读取
channel本质上是一种环形队列,包括接收方队列,发送方队列,还有互斥锁,结构如下
type hchan struct { qcount uint // total data in the queue(循环队列元素数量)
dataqsiz uint // size of the circular queue(循环队列大小)
buf unsafe.Pointer // points to an array of dataqsiz elements(循环队列指针)
elemsize uint16 //chan中元素大小
closed uint32 //是否已经close
elemtype *_type // element type(chan元素类型)
sendx uint // send index(send在buf中索引)
recvx uint // receive index(recv在buf中索引)
recvq waitq // list of recv waiters(receive的等待队列)
sendq waitq // list of send waiters(sender等待队列)
// lock protects all fields in hchan, as well as several
// fields in sudogs blocked on this channel.
//
// Do not change another G's status while holding this lock
// (in particular, do not ready a G), as this can deadlock
// with stack shrinking.
lock mutex //互斥锁,保护所有字段,上面注释已经讲得非常明确了
}
通过一个例子进行演示