golang高階部分

2021-09-07 07:51:52 字數 3096 閱讀 8107

在golang中,每乙個併發的執行單元叫做乙個goroutine;而channel則是它們之間的通訊機制,它可以讓乙個goroutine通過channel給另乙個goroutine傳送訊息;需要注意的是,每個channel都有乙個特殊的型別;

ch := make(chan int)

close(ch)  //關閉channel

2.1 無buffer channel

ch := make(chan int)  or   ch := make(chan int , 0)

乙個基於無快取channels的傳送操作將導致傳送者goroutine阻塞, 直到另乙個goroutine在相同的channels上執行接收操作, 當傳送的值通過channels成功傳輸之後, 兩個goroutine可以繼續執行後面的語句。 反之, 如果接收操作先發生, 那麼接收者goroutine也將阻塞, 直

到有另乙個goroutine在相同的channels上執行傳送操作。

基於無快取channels的傳送和接收操作將導致兩個goroutine做一次同步操作。 因為這個原因, 無快取channels有時候也被稱為同步channels。當通過乙個無快取channels傳送資料時, 接收者收到資料發生在喚醒傳送者goroutine之前;

2.2 單方向的channel

型別 chan<- int 表示乙個只傳送int的channel, 只能傳送不能接收。 相反, 型別 <-chan int 表示乙個只接收int的channel, 只能接收不能傳送。 ( 箭頭 <- 和關鍵字chan的相對位置表明了channel的方向。 ) 這種限制將在編譯期檢測。 

1  12 //out 只發 channel

2 13 // in

只收channel

3 14 func squares(out chan<- int, in

<-chan int)

7 18close(out)

8 19 }

2.3 帶buffer的channel

ch = make(chan string, 3)

向快取channel的傳送操作就是向內部快取佇列的尾部插入元素, 接收操作則是從佇列的頭部刪除元素。 如果內部快取佇列是滿的, 那麼傳送操作將阻塞直到因另乙個goroutine執行接收操作而釋放了新的佇列空間。 相反, 如果channel是空的, 接收操作將阻塞直到有另乙個

goroutine執行傳送操作而向佇列插入元素。

獲取channel的容量:cap(ch)     獲取channel資料的長度:len(ch)

三、select多路復用

1

package main23

import(4

"fmt

"5 //"

time"6

)78 /*

9select

19 */

2021

func main()

32}

33 }

一般情況下,我們沒法知道分別位於兩個goroutine事件x和y的執行順序,x是在y之前還是之後還是同時發生是沒法判斷的。 當我們能夠沒有辦法明確地確認乙個事件是在另乙個事件的前面或者後面發生的話, 就說明x和y這兩個事件是併發的。

如何避免競爭?

由於其它的goroutine不能夠直接訪問變數, 它們只能使用乙個channel來傳送給指定的goroutine請求來查詢更新變數。 這也就是go的口頭禪「不要使用共享資料來通訊;使用通訊來共享資料」。 乙個提供對乙個指定的變數通過cahnnel來請求

的goroutine叫做這個變數的監控(monitor)goroutine。

互斥原型實現:

1

var (

2 sema = make(chan struct{}, 1)

3balance int 4)

56func add(amount int) {}

8 balance = balance +amount

9<-sema10}

1112

func get() int {}

14 b :=balance

15<-sema16}

1718

import

"sync"19

var (

20mu sync.mutex

21balance int

22)

23func add(amount int)

2829

func get() int

func get() int

1415

func icon(name string) int

2.3 sync.waitgroup

先說說waitgroup的用途:它能夠一直等到所有的goroutine執行完成,並且阻塞主線程的執行,直到所有的goroutine執行完成。這裡要注意一下,他們的執行結果是沒有順序的,排程器不能保證多個 goroutine 執行次序,且程序退出時不會等待它們結束。

waitgroup總共有三個方法:add(delta int),done(),wait()。簡單的說一下這三個方法的作用。

add:新增或者減少等待goroutine的數量

done:相當於add(-1)

wait:執行阻塞,直到所有的waitgroup數量變成0

如:

golang中的同步是通過sync.waitgroup來實現的.waitgroup的功能:它實現了乙個類似佇列的結構,可以一直向佇列中新增任務,當任務完成後便從佇列中刪除,如果佇列中的任務沒有完全完成,可以通過wait()函式來出發阻塞,防止程式繼續進行,直到所有的佇列任務都完成為止.

waitgroup的特點是wait()可以用來阻塞直到佇列中的所有任務都完成時才解除阻塞,而不需要sleep乙個固定的時間來等待.但是其缺點是無法指定固定的goroutine數目.可能通過使用channel解決此問題。  

golang部分內建函式

參考官方文件 builtin 1 len 統計字串長度 中文字元位元組數為8 len str 2 new 分配記憶體 主要是分配值型別,如int float32 struct,返回的是指標 package main import fmt func main 3 make 分配記憶體 主要是分配引用型...

Golang併發模型 select高階

最近公司工作有點多,golang的select高階就這樣被拖沓啦,今天堅持把時間擠一擠,把吹的牛皮補上。前一篇文章 golang併發模型 輕鬆入門select 介紹了select的作用和它的基本用法,這次介紹它的3個高階特性。nil的通道永遠阻塞 如何跳出for selectselect 阻塞 當c...

Golang學習筆記 高階型別

高階型別 陣列 切片map 函式 介面 inte ce 結構體參考文件 長度不可變。int不用指定長度,為3。內部結構三個元素 指向底層陣列某個元素的指標 切片的長度 切片的容量。容量cap 從指標指向的元素到底層最後乙個元素的元素個數。雜湊表,關聯陣列。零值為nil,長度為0,不可以進行取值等操作...