1.GO语言进阶

1.1并发

1.1.1goroutine

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函数已经结束
}

1.1.2channel

1.1.2.1基础定义

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 //互斥锁,保护所有字段,上面注释已经讲得非常明确了
}

通过一个例子进行演示