最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang調(diào)度器GMP原理小結(jié)

 更新時(shí)間:2026年04月08日 09:09:34   作者:peace-chen  
本文主要介紹了Golang調(diào)度器GMP原理小結(jié),詳細(xì)描述了Goroutine的創(chuàng)建、執(zhí)行、阻塞、喚醒等場(chǎng)景下的調(diào)度過程,下面就來一起了解一下

?一、Golang “調(diào)度器” 的由來?

1.1 單進(jìn)程時(shí)代不需要調(diào)度器

每個(gè)程序就是一個(gè)進(jìn)程,知道一個(gè)程序運(yùn)行結(jié)束,下一個(gè)進(jìn)程才會(huì)執(zhí)行,一切的程序只能串行發(fā)生

弊端:

  • 單一的執(zhí)行流程,計(jì)算機(jī)只能一個(gè)任務(wù)一個(gè)任務(wù)處理
  • 進(jìn)程阻塞(IO訪問等)所帶來的CPU時(shí)間浪費(fèi)

1.2 多進(jìn)程/線程時(shí)代有了調(diào)度器需求(TODO 進(jìn)程和線程的區(qū)別)

一個(gè)進(jìn)程阻塞CPU可以立刻切換到其他進(jìn)程中去執(zhí)行(解決阻塞的問題),而且調(diào)度CPU的算法可以保證在運(yùn)行的進(jìn)程都可以被分配到CPU的運(yùn)行時(shí)間片。(宏觀看,似乎多個(gè)進(jìn)程是在同時(shí)被運(yùn)行)
弊端:

  • 進(jìn)程的創(chuàng)建、切換、銷毀,都會(huì)占用很長的時(shí)間,進(jìn)程過多會(huì)導(dǎo)致CPU利用率低,都拿去做進(jìn)程調(diào)度了
  • 高內(nèi)存占用(進(jìn)程虛擬內(nèi)存會(huì)占用4GB【32位操作系統(tǒng)】,而線程雖然占用小一點(diǎn),但是也需要大約4MB)。

1.3 協(xié)程來提高CPU利用率

優(yōu)點(diǎn):協(xié)程在用戶態(tài)線程完成切換調(diào)度,不會(huì)陷入到內(nèi)核態(tài),切換輕量快速

一個(gè)“用戶態(tài)線程”必須綁定一個(gè)“內(nèi)核態(tài)線程”,但是CPU并不知道有“用戶態(tài)線程”的存在,它只知道它運(yùn)行的是一個(gè)“內(nèi)核態(tài)線程”(Linux的PCB的進(jìn)程控制塊)。

再細(xì)分,內(nèi)核線程依然叫“線程(Thread)”,用戶態(tài)線程叫協(xié)程(co-routine)

既然一個(gè)協(xié)程(co-routine)可以綁定一個(gè)線程(Thread),那么能不能多個(gè)協(xié)程(co-routine)綁定一個(gè)或者多個(gè)線程(Thread)呢?基于以上思考,產(chǎn)生了以下三種協(xié)程和線程的映射關(guān)系;

1.3.1 N:1關(guān)系

N個(gè)協(xié)程綁定1個(gè)線程,即程序啟動(dòng)后只會(huì)創(chuàng)建一個(gè)調(diào)度線程,用來管理N個(gè)協(xié)程;

缺點(diǎn):用不了硬件的多核加速能力,協(xié)程阻塞會(huì)導(dǎo)致線程阻塞,失去并發(fā)能力;

1.3.2 1:1關(guān)系

一個(gè)協(xié)程綁定一個(gè)線程

缺點(diǎn):線程的創(chuàng)建、刪除和切換的代價(jià)都是由CPU來完成的,代價(jià)高,和直接使用多線程方式來說,沒帶來多大提升,有種脫褲子放屁的感覺;

1.3.3 M:N關(guān)系

M個(gè)協(xié)程綁定N個(gè)內(nèi)核線程,是N:1和1:1類型的結(jié)合,保留以上2種模型的優(yōu)點(diǎn)情況下,同時(shí)客服了以上2種模型的缺點(diǎn),實(shí)現(xiàn)較為復(fù)雜;

線程由CPU調(diào)度是搶占式的,協(xié)程由用戶態(tài)調(diào)度是協(xié)作式的,一個(gè)協(xié)程讓出CPU后,才能執(zhí)行下一個(gè)協(xié)程;

1.4 Go語言的協(xié)程goroutine

Go使用的goroutine是來自協(xié)程的概念,讓一組可復(fù)用的函數(shù)運(yùn)行在一組線程之上,及時(shí)有協(xié)程阻塞,該線程的其他協(xié)程也可以被runtime調(diào)度,轉(zhuǎn)移到其他可運(yùn)行的線程上;
優(yōu)點(diǎn):

  • 輕量,一個(gè)goroutine只占用幾KB內(nèi)存,能在有限的內(nèi)存空間內(nèi)支持大量goroutine,支持了更多的并發(fā)
  • 調(diào)度更靈活(runtime調(diào)度)

1.5 被廢棄的goroutine調(diào)度器

go 2012之前的調(diào)度器被廢棄,可以先看看之前的調(diào)度器存在的問題

M想要執(zhí)行、放回G都必須訪問全局的G隊(duì)列,并且M有多個(gè),即多線程訪問同一資源需要加鎖保證互斥/同步

弊端:

  • 創(chuàng)建、銷毀、調(diào)度G都需要每個(gè)M獲取全局隊(duì)列的鎖,形成了激烈的鎖競爭
  • 系統(tǒng)調(diào)用(CPU在M之間的切換)導(dǎo)致頻繁的線程阻塞和取消阻塞操作增加了系統(tǒng)開銷

二、Goroutine調(diào)度器的CMP模型的設(shè)計(jì)思想

新調(diào)度器中,除了M(thread)和G(goroutine),又引進(jìn)了P(Processor)

Processor:包含了運(yùn)行g(shù)oroutine的資源,如果線程想運(yùn)行g(shù)oroutine,必須先獲取p,p中還包含了可運(yùn)行的G隊(duì)列

2.1 GMP模型

Go中,線程是運(yùn)行g(shù)oroutine的實(shí)體,調(diào)度器的功能是將可運(yùn)行的goroutine分配到工作線程上;

  • 全局隊(duì)列(global queue):存放等待運(yùn)行的G
  • P的本地隊(duì)列:同全局隊(duì)列類型,存放的也是等待運(yùn)行的G,存放的數(shù)量有限,不超過256個(gè)。創(chuàng)建G’時(shí),G’優(yōu)先加入到P的本地隊(duì)列,如果本地隊(duì)列滿了,則會(huì)把本地隊(duì)列中一半的G移動(dòng)到全局隊(duì)列中
  • P列表:所有的P都在程序啟動(dòng)時(shí)創(chuàng)建,并保存在數(shù)組中,最多有GOMAXPROCS(可配置)個(gè)
  • M:線程想運(yùn)行任務(wù)就得獲取P,從P的本地隊(duì)列獲取G,P隊(duì)列為空時(shí),M也會(huì)嘗試從全局隊(duì)列拿一批G放到P的本地隊(duì)列中,或者從其他P的本地隊(duì)列偷一半放到自己的本地隊(duì)列中。M運(yùn)行G,G執(zhí)行之后,M會(huì)從P獲取下一個(gè)G,不斷重復(fù)

Goroutine調(diào)度器和OS調(diào)度器是通過M結(jié)合起來的,每個(gè)M都代表了一個(gè)內(nèi)核線程,OS調(diào)度器負(fù)責(zé)把內(nèi)核線程分配到CPU的核上執(zhí)行

2.1.1 有關(guān)P和M的個(gè)數(shù)問題

2.1.1.1 P

由啟動(dòng)時(shí)環(huán)境變量$GOAMXPROCES或者是由runtime的方法GOMAXPROCES()決定。這意味著在程序執(zhí)行的任意時(shí)刻,都只有$GOMAXPROCES個(gè)goroutine在同時(shí)運(yùn)行;

2.1.1.2 M

  • go語言本身的限制:go程序啟動(dòng)時(shí),會(huì)設(shè)置M的最大數(shù)量,默認(rèn)10000,但是內(nèi)核很難支持這么多的線程數(shù),因此這個(gè)限制可以忽略。
  • runtime/debug中的SetMaxThreads()函數(shù),可以設(shè)置M的最大數(shù)量。
  • 一個(gè)M阻塞了,會(huì)創(chuàng)建新的M。

M與P的數(shù)量沒有絕對(duì)的關(guān)系,一個(gè)M阻塞了,P就會(huì)去創(chuàng)建或者切換另一個(gè)M,所以,即使P的默認(rèn)數(shù)量是1,也有可能會(huì)創(chuàng)建很多個(gè)M出來;

2.1.2 P和M何時(shí)會(huì)被創(chuàng)建

2.1.1.1 P

在確定了P的最大數(shù)量n后,運(yùn)行是系統(tǒng)會(huì)根據(jù)這個(gè)數(shù)量創(chuàng)建n個(gè)p。

2.1.1.2 M

沒有足夠的M來關(guān)聯(lián)P并運(yùn)行其中的可運(yùn)行的G。比如所有的M此時(shí)都被阻塞住了,而P中還有很多就緒任務(wù),就會(huì)去尋找空閑的M,沒有空閑的,就會(huì)去創(chuàng)建新的M。

2.2 調(diào)度器的設(shè)計(jì)策略

復(fù)用線程:避免頻繁的創(chuàng)建、銷毀線程,增加系統(tǒng)開銷,而是對(duì)線程的復(fù)用。

  • work stealing機(jī)制:當(dāng)本線程無可以運(yùn)行的G時(shí),嘗試從其他線程綁定的P中偷取G,而不是銷毀線程;
  • hand off機(jī)制:當(dāng)本線程因?yàn)镚進(jìn)行系統(tǒng)調(diào)用阻塞時(shí),線程釋放綁定的P,把P轉(zhuǎn)移給其他空閑的線程執(zhí)行。
  • 可搶占:goroutine可以被搶占式調(diào)度,防止其他goroutine被餓死
  • 全局G隊(duì)列:當(dāng)M執(zhí)行work stealing從其他P中偷不到G時(shí),M可以從全局G隊(duì)列中獲取G

2.3 go func()調(diào)度流程

  1. 我們通過go func()來創(chuàng)建一個(gè)goroutine;
  2. 有兩個(gè)存儲(chǔ)G的隊(duì)列,一個(gè)是局部調(diào)度器P的本地隊(duì)列、一個(gè)是全局G隊(duì)列。新創(chuàng)建的G會(huì)先保存在P的本地隊(duì)列中,如果P的本地隊(duì)列已經(jīng)滿了,就會(huì)保存在全局的隊(duì)列中;
  3. G只能運(yùn)行在M中,一個(gè)M必須持有一個(gè)P,M與P是1:1的關(guān)系。M會(huì)從P的本地隊(duì)列彈出一個(gè)可執(zhí)行的G來執(zhí)行,如果P的本地隊(duì)列為空,就會(huì)嘗試從其他的MP組合中偷取一個(gè)可執(zhí)行的G來執(zhí)行;
  4. 一個(gè)M調(diào)度G執(zhí)行的過程是一個(gè)循環(huán)機(jī)制;
  5. 當(dāng)M執(zhí)行一個(gè)G的時(shí)候,如果發(fā)生了syscall或者其余阻塞操作,M會(huì)被阻塞,如果當(dāng)前有一些G在執(zhí)行,runtime會(huì)把這個(gè)線程M從P中摘除,然后再創(chuàng)建一個(gè)新的操作系統(tǒng)級(jí)別的線程(如果有空閑的線程就可以復(fù)用空閑線程)來服務(wù)與這個(gè)P;
  6. 當(dāng)M系統(tǒng)調(diào)用結(jié)束時(shí)候,這個(gè)G會(huì)嘗試獲取一個(gè)空閑的P執(zhí)行,并放入到這個(gè)P的本地隊(duì)列中。如果獲取不到P,那么這個(gè)線程M會(huì)變成休眠狀態(tài),加入到空閑線程中,然后這個(gè)G會(huì)被放入到全局隊(duì)列中;

2.4 調(diào)度器的生命周期

M0:啟動(dòng)程序后的編號(hào)為 0 的主線程,這個(gè) M 對(duì)應(yīng)的實(shí)例會(huì)在全局變量 runtime.m0 中,不需要在 heap 上分配,M0 負(fù)責(zé)執(zhí)行初始化操作和啟動(dòng)第一個(gè) G, 在之后 M0 就和其他的 M 一樣了。

G0:每次啟動(dòng)一個(gè) M 都會(huì)第一個(gè)創(chuàng)建的 goroutine,G0 僅用于負(fù)責(zé)調(diào)度的 G,G0 不指向任何可執(zhí)行的函數(shù),每個(gè) M 都會(huì)有一個(gè)自己的 G0。在調(diào)度或系統(tǒng)調(diào)用時(shí)會(huì)使用 G0 的??臻g,全局變量的 G0 是 M0 的 G0。

追蹤代碼:

package main
import "fmt"
func main() {
    fmt.Println("Hello world")
}
  1. runtime創(chuàng)建最初的線程m0和goroutine g0,并把2者關(guān)聯(lián);
  2. 調(diào)度器初始化:初始化m0、棧、垃圾回收,以及創(chuàng)建和初始化由GOMAXPROCES個(gè)P構(gòu)成的P列表;
  3. 實(shí)例代碼中的main函數(shù)是main.main,runtime中也有一個(gè)main函數(shù)——runtime.main,代碼經(jīng)過編譯后,runtime.main會(huì)調(diào)用main.main,程序啟動(dòng)時(shí)會(huì)為runtime.main創(chuàng)建goroutine,稱它為main goroutine吧,然后把main goroutine加入到P的本地隊(duì)列;
  4. 啟動(dòng)m0,m0已經(jīng)綁定了P,會(huì)從P的本地隊(duì)列中獲取G,獲取到main goroutine;
  5. G擁有棧,M根據(jù)G中的棧信息和調(diào)度信息設(shè)置運(yùn)行環(huán)境;
  6. M運(yùn)行G;
  7. G退出,再次回到M獲取可運(yùn)行的G,這樣重復(fù)下去,直到main.main退出,runtime.main執(zhí)行defer和panic處理,或者調(diào)用runtime.exit退出程序;?

三、Go調(diào)度器調(diào)度場(chǎng)景過程全解析

3.1 場(chǎng)景一

P擁有G1,M1獲取P后開始運(yùn)行G1,G1使用go func()創(chuàng)建了G2,為了局部性,G2優(yōu)先加入到P1的本地隊(duì)列;

3.2 場(chǎng)景二

G1運(yùn)行完成后(函數(shù):goexit),M1上運(yùn)行的goroutine切換為G0,G0負(fù)責(zé)調(diào)度時(shí)協(xié)程的切換(函數(shù):scheduler)。從P的本地隊(duì)列獲取G2,從G0切換到G2,并開始運(yùn)行G2(函數(shù):excute)。實(shí)現(xiàn)了線程M1的復(fù)用;

3.3 場(chǎng)景三

假設(shè)每個(gè)P的本地隊(duì)列只能存3個(gè)G。G2要?jiǎng)?chuàng)建6個(gè)G,前三個(gè)G(G3,G4,G5)已經(jīng)加入到P1的本地隊(duì)列中,此時(shí)P1的本地隊(duì)列滿了;

3.4 場(chǎng)景四

G2 在創(chuàng)建 G7 的時(shí)候,發(fā)現(xiàn) P1 的本地隊(duì)列已滿,需要執(zhí)行負(fù)載均衡 (把 P1 中本地隊(duì)列中前一半的 G,還有新創(chuàng)建 G 轉(zhuǎn)移到全局隊(duì)列)
(實(shí)現(xiàn)中并不一定是新的 G,如果 G 是 G2 之后就執(zhí)行的,會(huì)被保存在本地隊(duì)列,利用某個(gè)老的 G 替換新 G 加入全局隊(duì)列)

這些G被轉(zhuǎn)移到全局隊(duì)列時(shí),會(huì)被打亂順序,所以G3,G4,G7被轉(zhuǎn)移到全局隊(duì)列中的順序無規(guī)則;

3.5 場(chǎng)景五

G2創(chuàng)建G8時(shí),P1的本地隊(duì)列未滿,所以G8會(huì)被加入到P1的本地隊(duì)列中

G8 加入到 P1 點(diǎn)本地隊(duì)列的原因還是因?yàn)?P1 此時(shí)在與 M1 綁定,而 G2 此時(shí)是 M1 在執(zhí)行。所以 G2 創(chuàng)建的新的 G 會(huì)優(yōu)先放置到自己的 M 綁定的 P 上

3.6 場(chǎng)景六

在創(chuàng)建G時(shí),運(yùn)行的G會(huì)嘗試喚醒其他空閑的P和M組合去執(zhí)行;

假定 G2 喚醒了 M2,M2 綁定了 P2,并運(yùn)行 G0,但 P2 本地隊(duì)列沒有 G,M2 此時(shí)為自旋線程(沒有 G 但為運(yùn)行狀態(tài)的線程,不斷尋找 G)

3.7 場(chǎng)景七

M2 嘗試從全局隊(duì)列 (簡稱 “GQ”) 取一批 G 放到 P2 的本地隊(duì)列(函數(shù):findrunnable())。M2 從全局隊(duì)列取的 G 數(shù)量符合下面的公式:

n = min(len(GQ)/GOMAXPROCS + 1, len(GQ/2))

至少從全局隊(duì)列取 1 個(gè) g,但每次不要從全局隊(duì)列移動(dòng)太多的 g 到 p 本地隊(duì)列,給其他 p 留點(diǎn)。這是從全局隊(duì)列到 P 本地隊(duì)列的負(fù)載均衡


假定我們場(chǎng)景中一共有 4 個(gè) P(GOMAXPROCS 設(shè)置為 4,那么我們?cè)试S最多就能用 4 個(gè) P 來供 M 使用)。所以 M2 只從能從全局隊(duì)列取 1 個(gè) G(即 G3)移動(dòng) P2 本地隊(duì)列,然后完成從 G0 到 G3 的切換,運(yùn)行 G3

3.8 場(chǎng)景八

假設(shè) G2 一直在 M1 上運(yùn)行,經(jīng)過 2 輪后,M2 已經(jīng)把 G7、G4 從全局隊(duì)列獲取到了 P2 的本地隊(duì)列并完成運(yùn)行,全局隊(duì)列和 P2 的本地隊(duì)列都空了,如場(chǎng)景 8 圖的左半部分

全局隊(duì)列已經(jīng)沒有 G,那 m 就要執(zhí)行 work stealing (偷取):從其他有 G 的 P 哪里偷取一半 G 過來,放到自己的 P 本地隊(duì)列。P2 從 P1 的本地隊(duì)列尾部取一半的 G,本例中一半則只有 1 個(gè) G8,放到 P2 的本地隊(duì)列并執(zhí)行;

3.9 場(chǎng)景九

G1 本地隊(duì)列 G5、G6 已經(jīng)被其他 M 偷走并運(yùn)行完成,當(dāng)前 M1 和 M2 分別在運(yùn)行 G2 和 G8,M3 和 M4 沒有 goroutine 可以運(yùn)行,M3 和 M4 處于自旋狀態(tài),它們不斷尋找 goroutine。

為什么要讓 m3 和 m4 自旋,自旋本質(zhì)是在運(yùn)行,線程在運(yùn)行卻沒有執(zhí)行 G,就變成了浪費(fèi) CPU. 為什么不銷毀現(xiàn)場(chǎng),來節(jié)約 CPU 資源。因?yàn)閯?chuàng)建和銷毀 CPU 也會(huì)浪費(fèi)時(shí)間,我們希望當(dāng)有新 goroutine 創(chuàng)建時(shí),立刻能有 M 運(yùn)行它,如果銷毀再新建就增加了時(shí)延,降低了效率。當(dāng)然也考慮了過多的自旋線程是浪費(fèi) CPU,所以系統(tǒng)中最多有 GOMAXPROCS 個(gè)自旋的線程 (當(dāng)前例子中的 GOMAXPROCS=4,所以一共 4 個(gè) P),多余的沒事做線程會(huì)讓他們休眠。

3.10 場(chǎng)景十

假定當(dāng)前除了 M3 和 M4 為自旋線程,還有 M5 和 M6 為空閑的線程 (沒有得到 P 的綁定,注意我們這里最多就只能夠存在 4 個(gè) P,所以 P 的數(shù)量應(yīng)該永遠(yuǎn)是 M>=P, 大部分都是 M 在搶占需要運(yùn)行的 P),G8 創(chuàng)建了 G9,G8 進(jìn)行了阻塞的系統(tǒng)調(diào)用,M2 和 P2 立即解綁,P2 會(huì)執(zhí)行以下判斷:如果 P2 本地隊(duì)列有 G、全局隊(duì)列有 G 或有空閑的 M,P2 都會(huì)立馬喚醒 1 個(gè) M 和它綁定,否則 P2 則會(huì)加入到空閑 P 列表,等待 M 來獲取可用的 p。本場(chǎng)景中,P2 本地隊(duì)列有 G9,可以和其他空閑的線程 M5 綁定

3.11 場(chǎng)景十一

G8 創(chuàng)建了 G9,假如 G8 進(jìn)行了非阻塞系統(tǒng)調(diào)用

M2 和 P2 會(huì)解綁,但 M2 會(huì)記住 P2,然后 G8 和 M2 進(jìn)入系統(tǒng)調(diào)用狀態(tài)。當(dāng) G8 和 M2 退出系統(tǒng)調(diào)用時(shí),會(huì)嘗試獲取 P2,如果無法獲取,則獲取空閑的 P,如果依然沒有,G8 會(huì)被記為可運(yùn)行狀態(tài),并加入到全局隊(duì)列,M2 因?yàn)闆]有 P 的綁定而變成休眠狀態(tài) (長時(shí)間休眠等待 GC 回收銷毀)。

到此這篇關(guān)于Golang調(diào)度器GMP原理小結(jié)的文章就介紹到這了,更多相關(guān)Golang調(diào)度器GMP內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語言簡介和環(huán)境配置

    Go語言簡介和環(huán)境配置

    Go語言保證了既能到達(dá)靜態(tài)編譯語言的安全和性能,又達(dá)到了動(dòng)態(tài)語言開發(fā)速度和易維護(hù)性,有人形容Go語言:Go=?C?+?Python?,?說明Go語言既有C靜態(tài)語言程序的運(yùn)行速度,又能達(dá)到Python動(dòng)態(tài)語言的快速開發(fā),這篇文章主要介紹了Go介紹和環(huán)境配置,需要的朋友可以參考下
    2022-07-07
  • 深度解密 Go 語言中的 sync.Pool

    深度解密 Go 語言中的 sync.Pool

    sync.Pool 是 sync 包下的一個(gè)組件,可以作為保存臨時(shí)取還對(duì)象的一個(gè)“池子”。這篇文章主要介紹了深度解密 Go 語言中的sync.Pool,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-04-04
  • 15個(gè)Golang中時(shí)間處理的實(shí)用函數(shù)

    15個(gè)Golang中時(shí)間處理的實(shí)用函數(shù)

    在Go編程中,處理日期和時(shí)間是一項(xiàng)常見任務(wù),涉及到精確性和靈活性,本文將介紹一系列實(shí)用函數(shù),它們充當(dāng)time包的包裝器,需要的可以參考下
    2024-01-01
  • Go 代碼生成工具詳解

    Go 代碼生成工具詳解

    這篇文章主要介紹了Go 代碼生成工具詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • go語言制作的zip壓縮程序

    go語言制作的zip壓縮程序

    這篇文章主要介紹了go語言制作的zip壓縮程序,其主體思路是首先創(chuàng)建一個(gè)讀寫緩沖,然后用壓縮器包裝該緩沖,用Walk方法來將所有目錄下的文件寫入zip,有需要的小伙伴參考下。
    2015-03-03
  • goland 清除所有的默認(rèn)設(shè)置操作

    goland 清除所有的默認(rèn)設(shè)置操作

    這篇文章主要介紹了goland 清除所有的默認(rèn)設(shè)置操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • Golang 經(jīng)典校驗(yàn)庫 validator 用法解析

    Golang 經(jīng)典校驗(yàn)庫 validator 用法解析

    這篇文章主要為大家介紹了Golang 經(jīng)典校驗(yàn)庫 validator 用法解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • golang中net的tcp服務(wù)使用

    golang中net的tcp服務(wù)使用

    這篇文章主要介紹了golang中net的tcp服務(wù)使用,文章通過服務(wù)端監(jiān)聽端口 展開主題的詳細(xì)內(nèi)容,具有一定的參考價(jià)值,需要的 小伙伴可以參考一下
    2022-04-04
  • golang開發(fā)?gorilla?websocket的使用示例詳解

    golang開發(fā)?gorilla?websocket的使用示例詳解

    這篇文章主要介紹了golang開發(fā)?gorilla?websocket的使用示例詳解,介紹了websocket的簡單使用,我們使用的版本是1.3.0,具體操作方法跟隨小編一起學(xué)習(xí)吧
    2024-05-05
  • Go語言入門之基礎(chǔ)語法和常用特性解析

    Go語言入門之基礎(chǔ)語法和常用特性解析

    這篇文章主要給大家講解了Go語言的基礎(chǔ)語法和常用特性解析,比較適合入門小白,文中通過代碼示例介紹的非常詳細(xì),對(duì)我們學(xué)習(xí)Go語言有一定的幫助,需要的朋友可以參考下
    2023-07-07

最新評(píng)論

沙坪坝区| 门源| 绥滨县| 房产| 泸西县| 汽车| 靖西县| 杭锦旗| 涿州市| 长子县| 九龙城区| 桑日县| 南投市| 郁南县| 广宁县| 唐河县| 东乡族自治县| 焦作市| 莫力| 诸城市| 沂南县| 阿拉善右旗| 景宁| 高州市| 余庆县| 德惠市| 大关县| 大新县| 武威市| 美姑县| 张家口市| 茌平县| 县级市| 前郭尔| 鄂托克旗| 福安市| 毕节市| 叙永县| 临沂市| 遂平县| 利辛县|