欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go語(yǔ)言并發(fā)之context標(biāo)準(zhǔn)庫(kù)的使用詳解

 更新時(shí)間:2023年06月16日 10:57:26   作者:242030  
Context的出現(xiàn)是為了解決在大型應(yīng)用程序中的并發(fā)環(huán)境下,協(xié)調(diào)和管理多個(gè)goroutine之間的通信、超時(shí)和取消操作的問題,本文就來(lái)和大家簡(jiǎn)單聊聊它的具體用法,希望對(duì)大家有所幫助

1、Go語(yǔ)言并發(fā)之context標(biāo)準(zhǔn)庫(kù)

Go中的 goroutine 之間沒有父與子的關(guān)系,也就沒有所謂子進(jìn)程退出后的通知機(jī)制,多個(gè) goroutine 都是平行地被調(diào)度,多個(gè) goroutine 如何協(xié)作工作涉及通信、同步、通知和退出四個(gè)方面。

  • 通信:chan 通道當(dāng)然是 goroutine 之間通信的基礎(chǔ),注意這里的通信主要是指程序的數(shù)據(jù)通道。
  • 同步:不帶緩沖的 chan 提供了一個(gè)天然的同步等待機(jī)制;當(dāng)然 sync.WaitGroup 也為多個(gè) goroutine 協(xié)同工作提供一種同步等待機(jī)制。
  • 通知:這個(gè)通知和上面通信的數(shù)據(jù)不一樣,通知通常不是業(yè)務(wù)數(shù)據(jù),而是管理、控制流數(shù)據(jù)。要處理這個(gè)也好辦,在輸入端綁定兩個(gè) chan,一個(gè)用于業(yè)務(wù)流數(shù)據(jù),另一個(gè)用于異常通知數(shù)據(jù),然后通過 select 收斂進(jìn)行處理。這個(gè)方案可以解決簡(jiǎn)單的問題,但不是一個(gè)通用的解決方案。
  • 退出:goroutine 之間沒有父子關(guān)系,如何通知 goroutine 退出?可以通過增加一個(gè)單獨(dú)的通道,借助通道和select 的廣播機(jī)制實(shí)現(xiàn)退出。

Go語(yǔ)言在語(yǔ)法上處理某個(gè) goroutine 退出通知機(jī)制很簡(jiǎn)單。但是遇到復(fù)雜的并發(fā)結(jié)構(gòu)處理起來(lái)就顯得力不從心。

實(shí)際編程中 goroutine 會(huì)拉起新的 goroutine,新的 goroutine 又會(huì)拉起另一個(gè)新的 goroutine,最終形成一個(gè)樹狀的結(jié)構(gòu),由于 goroutine 里并沒有父子的概念,這個(gè)樹狀的結(jié)構(gòu)只是在程序員頭腦中抽象出來(lái)的,程序的執(zhí)行模型并沒有維護(hù)這么一個(gè)樹狀結(jié)構(gòu)。怎么通知這個(gè)樹狀上的所有 goroutine 退出??jī)H依靠語(yǔ)法層面的支持顯然比較難處理。為此 Go1.7 提供了一個(gè)標(biāo)準(zhǔn)庫(kù) context 來(lái)解決這個(gè)問題。它提供兩種功能:退出通知和元數(shù)據(jù)傳遞。

context 庫(kù)的設(shè)計(jì)目的就是跟蹤 goroutine 調(diào)用,在其內(nèi)部維護(hù)一個(gè)調(diào)用樹,并在這些調(diào)用樹中傳遞通知和元數(shù)據(jù)。

1.1 Context的設(shè)計(jì)目的

context 庫(kù)的設(shè)計(jì)目的就是跟蹤 goroutine 調(diào)用樹,并在這些 gouroutine 調(diào)用樹中傳遞通知和元數(shù)據(jù)。兩個(gè)目的:

(1)、退出通知機(jī)制:通知可以傳遞給整個(gè)goroutine 調(diào)用樹上的每一個(gè)goroutine。

(2)、傳遞數(shù)據(jù):數(shù)據(jù)可以傳遞給整個(gè)goroutine 調(diào)用樹上的每一個(gè)goroutine。

1.2 基本數(shù)據(jù)結(jié)構(gòu)

在介紹 context 包之前,先理解context包的整體工作機(jī)制:第一個(gè)創(chuàng)建Context的goroutine被稱為root節(jié)點(diǎn)。

root節(jié)點(diǎn)負(fù)責(zé)創(chuàng)建一個(gè)實(shí)現(xiàn)Context接口的具體對(duì)象,并將該對(duì)象作為參數(shù)傳遞到其新拉起的goroutine,下游的goroutine可以繼續(xù)封裝該對(duì)象,再傳遞到更下游的goroutine。

Context 對(duì)象在傳遞的過程中最終形成一個(gè)樹狀的數(shù)據(jù)結(jié)構(gòu),這樣通過位干root節(jié)點(diǎn)(樹的根節(jié)點(diǎn))的Context 對(duì)象就能遍歷整個(gè)Context 對(duì)象樹,通知和消息就可以通過root節(jié)點(diǎn)傳遞出去,實(shí)現(xiàn)了上游 goroutine 對(duì)下游goroutine的消息傳遞。

1.2.1 Context接口

Context 是一個(gè)基本接口,所有的 Context 對(duì)象都要實(shí)現(xiàn)該接口,context 的使用者在調(diào)用接口中都使用 Context作為參數(shù)類型。

type Context interface{
    // 如果Context實(shí)現(xiàn)了超時(shí)控制,則該方法返回ok true,deadline為超時(shí)時(shí)間,否則ok為false
    Deadline() (deadline time.Time,ok bool)
    // 后端被調(diào)的goroutine應(yīng)該監(jiān)聽該方法返回的chan,以便及時(shí)釋放資源
    Done() <-chan struct{}
    // Done返回的chan收到通知的時(shí)候,才可以訪問Err()獲知因?yàn)槭裁丛虮蝗∠?
    Err()error
    // 可以訪問上游 goroutine 傳遞給下游 goroutine 的值
    Value(key interface{}) interface{}
}

1.2.2 canceler接口

canceler 接口是一個(gè)擴(kuò)展接口,規(guī)定了取消通知的 Context 具體類型需要實(shí)現(xiàn)的接口。

context 包中的具體類型 cancelctx 和 timerCtx 都實(shí)現(xiàn)了該接口。

1.2.3 empty Context結(jié)構(gòu)

emptyCtx 實(shí)現(xiàn)了 Context 接口,但不具備任何功能,因?yàn)槠渌械姆椒ǘ际强諏?shí)現(xiàn)。其存在的目的是作為Context 對(duì)象樹的根(root 節(jié)點(diǎn))。因?yàn)閏ontext包的使用思路就是不停地調(diào)用context 包提供的包裝函數(shù)來(lái)創(chuàng)建具有特殊功能的Context 實(shí)例,每一個(gè)Context 實(shí)例的創(chuàng)建都以上一個(gè)Context對(duì)象為參數(shù),最終形成一個(gè)樹狀的結(jié)構(gòu)。

1.2.4 cancelCtx

cancelCtx 是一個(gè)實(shí)現(xiàn)了Context接口的具體類型,同時(shí)實(shí)現(xiàn)了conceler接口。conceler具有退出通知方法。注意退出通知機(jī)制不但能通知己,也能逐層通知其children 節(jié)點(diǎn)。

1.2.5 timerCtx

timerCtx 是一個(gè)實(shí)現(xiàn)了Context接口的具體類型,內(nèi)部封裝了cancelCtx類型實(shí)例,同時(shí)有一個(gè) deadline 變量,用來(lái)實(shí)現(xiàn)定時(shí)退出通知。

1.2.6 valueCtx

valueCtx 是一個(gè)實(shí)現(xiàn)了Context接口的具體類型,內(nèi)部封裝了Context接口類型,同時(shí)封裝了一個(gè)k/v的存儲(chǔ)變量,valueCtx 可用來(lái)傳遞通知信息。

1.3 API函數(shù)

下面這兩個(gè)函數(shù)是構(gòu)造 Context 取消樹的根節(jié)點(diǎn)對(duì)象,根節(jié)點(diǎn)對(duì)象用作后續(xù) With 包裝函數(shù)的實(shí)參。

func Background() Context
func TODO() Context

With 包裝函數(shù)用來(lái)構(gòu)建不同功能的 Context 具體對(duì)象。

(1)、創(chuàng)建一個(gè)帶有退出通知的 Context 具體對(duì)象,內(nèi)部創(chuàng)建一個(gè) cancelCtx 的類型實(shí)例。

func WithCancel(parent Context)(Context,CancelFunc)

(2)、創(chuàng)建一個(gè)帶有超時(shí)通知的 Context 具體對(duì)象,內(nèi)部創(chuàng)建一個(gè) timerCtx 的類型實(shí)例。

func WithDeadline(parent Context,deadline time.Time)(Context,CancelFunc)

(3)、創(chuàng)建一個(gè)帶有超時(shí)通知的 Context 具體對(duì)象,內(nèi)部創(chuàng)建一個(gè) timerCtx 的類型實(shí)例。

func WithTimeout(parent Context,timeout time.Duration)(Context,CancelFunc)

(4)、創(chuàng)建一個(gè)能夠傳遞數(shù)據(jù)的 Context 具體對(duì)象,內(nèi)部創(chuàng)建一個(gè) valueCtx 的類型實(shí)例。

func WithValue(parent Context,key,val interface{})Context

這些函數(shù)都有一個(gè)共同的特點(diǎn)—— parent 參數(shù),其實(shí)這就是實(shí)現(xiàn) Context 通知樹的必備條件。在 goroutine 的調(diào)用鏈中,Context 的實(shí)例被逐層地包裝并傳遞,每層又可以對(duì)傳講來(lái)的 Context 實(shí)例再封裝自己所需的功能,整個(gè)調(diào)用樹需要一個(gè)數(shù)據(jù)結(jié)構(gòu)來(lái)維護(hù),這個(gè)維護(hù)邏輯在這些包裝函數(shù)內(nèi)部實(shí)現(xiàn)。

1.4 輔助函數(shù)

前面描述的 With 開頭的構(gòu)造函數(shù)是給外部程序使用的 API 接口函數(shù)。Context 具體對(duì)象的鏈條關(guān)系是在 With 函數(shù)的內(nèi)部維護(hù)的。

func propagateCancel(parent Context,child canceler)

1.5 context的用法

package main
import (
	"context"
	"fmt"
	"time"
)
// 定義一個(gè)新的類型包含Context字段
type otherContext struct {
	context.Context
}
func main() {
	// 創(chuàng)建一個(gè)帶有退出通知的Context具體對(duì)象:*cancelCtx
	ctxA, cancel := context.WithCancel(context.Background())
	go work(ctxA, "work1")
	// 超時(shí)3秒計(jì)算
	tm := time.Now().Add(3 * time.Second)
	// 創(chuàng)建一個(gè)帶有超時(shí)通知的Context具體對(duì)象:*timerCtx
	ctxB, _ := context.WithDeadline(ctxA, tm)
	go work(ctxB, "work2")
	oc := otherContext{ctxB}
	// 創(chuàng)建一個(gè)能夠傳遞數(shù)據(jù)的Context具體對(duì)象:*cancelCtx
	ctxC := context.WithValue(oc, "key", "god andes,pass from main ")
	go workWithValue(ctxC, "work3")
	time.Sleep(10 * time.Second)
	cancel()
	// 這5秒沒有什么作用
	time.Sleep(5 * time.Second)
	fmt.Println("main stop")
}
// 工作
func work(ctx context.Context, name string) {
	for {
		select {
		case <-ctx.Done():
			fmt.Printf("%s get msg to cancel\n", name)
			return
		default:
			fmt.Printf("%s is running \n", name)
			time.Sleep(1 * time.Second)
		}
	}
}
// 根據(jù)context傳遞值
func workWithValue(ctx context.Context, name string) {
	for {
		select {
		case <-ctx.Done():
			fmt.Printf("%s get msg to cancel\n", name)
			return
		default:
			value := ctx.Value("key").(string)
			fmt.Printf("%s is running value=%s \n", name, value)
			time.Sleep(1 * time.Second)
		}
	}
}

程序輸出

work3 is running value=god andes,pass from main
work1 is running
work2 is running
work1 is running
work3 is running value=god andes,pass from main
work2 is running
work3 is running value=god andes,pass from main
work2 is running
work1 is running
work1 is running
work3 get msg to cancel
work2 get msg to cancel
work1 is running
work1 is running
work1 is running
work1 is running
work1 is running
work1 is running
work1 get msg to cancel
main stop

上面的輸出中:

work1 is running會(huì)輸出10次,因?yàn)闀?huì)休眠10秒。

work2 is running會(huì)輸出3次,因?yàn)槌瑫r(shí)時(shí)間為3秒。

work3 is running也會(huì)輸出3次,因?yàn)樗腸ontext取決于work2的context。

在使用 Context 的過程中,程序在底層實(shí)際上維護(hù)了兩條關(guān)系鏈,理解這個(gè)關(guān)系鏈對(duì)理解 context 包非常有好處,兩條引用關(guān)系鏈如下。

(1)、children key 構(gòu)成從根到葉子 Context 實(shí)例的引用關(guān)系,這個(gè)關(guān)系在調(diào)用 With 函數(shù)時(shí)進(jìn)行維護(hù)(調(diào)用上文介紹的 propagateCancel(parent Context,child canceler) 函數(shù)維護(hù)),程序有一層這樣的樹狀結(jié)構(gòu)(本示例是一個(gè)鏈表結(jié)構(gòu)):

ctxa.children--->ctxb
ctxb.children--->ctxc

這個(gè)樹提供一種從根節(jié)點(diǎn)開始遍歷樹的方法,context 包的取消廣播通知的核心就是基于這一點(diǎn)實(shí)現(xiàn)的。取消通知沿著這條鏈從根節(jié)點(diǎn)向下層節(jié)點(diǎn)逐層廣播。當(dāng)然也可以在任意一個(gè)子樹上調(diào)用取消通知,一樣會(huì)擴(kuò)散到整棵樹。示例程序中 ctxa 收到退出通知,會(huì)通知其綁定 work1,同時(shí)會(huì)廣播給 ctxb 和 ctxc 綁定的 work2 和 work3。同理,ctxb 收到退出通知,會(huì)通知到其綁定的 work2,同時(shí)會(huì)廣播給 ctxc 綁定的 work3。

(2)、在構(gòu)造 Context 的對(duì)象中不斷地包裹 Context 實(shí)例形成一個(gè)引用關(guān)系鏈,這個(gè)關(guān)系鏈的方向是相反的,是自底向上的。示例程序中多個(gè) Context 對(duì)象的關(guān)系如下:

# 自底向上
ctxc.Context -->oc
ctxc.Context.Context -->ctxb
ctxc.Context.Context.cancelCtx-->ctxa
ctxc.Context.Context.cancelCtx.Context-->new(emptyCtx)//context.Background()

這個(gè)關(guān)系鏈主要用來(lái)切斷當(dāng)前 Context 實(shí)例和上層的 Context 實(shí)例之間的關(guān)系,比如 ctxb 調(diào)用了退出通知或定時(shí)器到期了,ctxb 后續(xù)就沒有必要在通知廣播樹上繼續(xù)存在,它需要找到自己的 parent,然后執(zhí)行delete(parent.children,ctxb),把自己從廣播樹上清理掉。

整個(gè)關(guān)系鏈如圖所示:

通過上文示例梳理出使用 Context 包的一般流程如下:

(1)、創(chuàng)建一個(gè) Context 根對(duì)象。

func Background() Context
func TODO() Context

(2)、包裝上一步創(chuàng)建的 Context 對(duì)象,使其具有特定的功能。

這些包裝函數(shù)是 context package 的核心,幾乎所有的封裝都是從包裝函數(shù)開始的。原因很簡(jiǎn)單,使用 context包的核心就是使用其退出通知廣播功能。

func WithCancel(parent Context)(ctx Context,cancel CancelFunc)
func WithTimeout(parent Context,timeout time.Duration)(Context,CancelFunc)
func WithDeadline(parent Context, deadline time.Time)(Context,CancelFunc)
func WithValue(parent Context,key,val interface{}) Context

(3)、將上一步創(chuàng)建的對(duì)象作為實(shí)參傳給后續(xù)啟動(dòng)的并發(fā)函數(shù)(通常作為函數(shù)的第一個(gè)參數(shù)),每個(gè)并發(fā)函數(shù)內(nèi)部可以繼續(xù)使用包裝函數(shù)對(duì)傳進(jìn)來(lái)的 Context 對(duì)象進(jìn)行包裝,添加自己所需的功能。

(4)、頂端的 goroutine 在超時(shí)后調(diào)用 cancel 退出通知函數(shù),通知后端的所有 goroutine 釋放資源。

(5)、后端的 goroutine 通過 select 監(jiān)聽 Context.Done() 返回的 chan,及時(shí)響應(yīng)前端 goroutine 的退出通知,一般停止本次處理,釋放所占用的資源。

1.6 使用context傳遞數(shù)據(jù)的爭(zhēng)議

該不該使用context傳遞數(shù)據(jù):

首先要清楚使用 context 包主要是解決 goroutine 的通知退出,傳遞數(shù)據(jù)是其一個(gè)額外功能??梢允褂盟鼈鬟f一些元信息,總之使用 context 傳遞的信息不能影響正常的業(yè)務(wù)流程,程序不要期待在 context 中傳遞一些必需的參數(shù)等,沒有這些參數(shù),程序也應(yīng)該能正常工作。

在context中傳遞數(shù)據(jù)的壞處:

(1)、傳遞的都是 interface{} 類型的值,編譯器不能進(jìn)行嚴(yán)格的類型校驗(yàn)。

(2)、從 interface{} 到具體類型需要使用類型斷言和接口查詢,有一定的運(yùn)行期開銷和性能損失。

(3)、值在傳遞過程中有可能被后續(xù)的服務(wù)覆蓋,且不易被發(fā)現(xiàn)。

(4)、傳遞信息不簡(jiǎn)明,較晦澀;不能通過代碼或文檔一眼看到傳遞的是什么,不利于后續(xù)維護(hù)。

context應(yīng)該傳遞什么數(shù)據(jù):

(1)、日志信息。

(2)、調(diào)試信息。

(3)、不影響業(yè)務(wù)主邏輯的可選數(shù)據(jù)。

context 包提供的核心的功能是多個(gè) goroutine 之間的退出通知機(jī)制,傳遞數(shù)據(jù)只是一個(gè)輔助功能,應(yīng)謹(jǐn)慎使用context 傳遞數(shù)據(jù)。

1.7 Context常用案例

1.7.1 主協(xié)程主動(dòng)調(diào)用cancel()取消子context

package main
import (
	"context"
	"fmt"
	"time"
)
func handler() {
	fmt.Println("handler start...", time.Now())
	ctx, cancel := context.WithCancel(context.Background())
	go do(ctx)
	// 子孫攜程中的ctx會(huì)被取消
	cancel()
	time.Sleep(5 * time.Second)
	fmt.Println("handler end...", time.Now())
}
func do(ctx context.Context) {
	i := 1
	for {
		time.Sleep(1 * time.Second)
		select {
		case <-ctx.Done():
			fmt.Println("done", time.Now())
			return
		default:
			fmt.Printf("work %d seconds: %v\n", i, time.Now())
		}
		i++
	}
}
func main() {
	fmt.Println("main start...")
	handler()
	fmt.Println("main end...")
}

程序輸出

main start...
handler start... 2023-02-06 12:18:29.3556787 +0800 CST m=+0.002016401
done 2023-02-06 12:18:30.3665436 +0800 CST m=+1.012881301
handler end... 2023-02-06 12:18:34.365822 +0800 CST m=+5.012159701
main end...

通過輸出我們可以看出來(lái),在主協(xié)程調(diào)用了 cancel() 之后,子協(xié)程中的 ctx 會(huì)被主動(dòng)關(guān)閉掉,延遲時(shí)間是1秒,會(huì)看到打印 done。

package main
import (
	"context"
	"fmt"
	"time"
)
func handler() {
	fmt.Println("handler start...", time.Now())
	ctx, _ := context.WithCancel(context.Background())
	go do(ctx)
	// 子孫攜程中的ctx會(huì)被取消
	time.Sleep(5 * time.Second)
	fmt.Println("handler end...", time.Now())
}
func do(ctx context.Context) {
	i := 1
	for {
		time.Sleep(1 * time.Second)
		select {
		case <-ctx.Done():
			fmt.Println("done", time.Now())
			return
		default:
			fmt.Printf("work %d seconds: %v\n", i, time.Now())
		}
		i++
	}
}
func main() {
	fmt.Println("main start...")
	handler()
	fmt.Println("main end...")
}

程序輸出

main start...
handler start... 2023-06-10 10:49:42.9315016 +0800 CST m=+0.002174101
work 1 seconds: 2023-06-10 10:49:43.9404127 +0800 CST m=+1.011085201
work 2 seconds: 2023-06-10 10:49:44.941524 +0800 CST m=+2.012196501
work 3 seconds: 2023-06-10 10:49:45.9422753 +0800 CST m=+3.012947801
work 4 seconds: 2023-06-10 10:49:46.9426627 +0800 CST m=+4.013335201
handler end... 2023-06-10 10:49:47.9421403 +0800 CST m=+5.012812801
main end...

從結(jié)果看出,我們?nèi)绻粓?zhí)行 cancel(),則會(huì)在設(shè)置的5秒睡眠時(shí)間內(nèi)執(zhí)行 work。

1.7.2 超時(shí)之后,調(diào)用cancle()

package main
import (
	"context"
	"fmt"
	"time"
)
func handler() {
	fmt.Println("handler start...", time.Now())
	// 設(shè)置2秒的超時(shí)時(shí)間
	ctx, _ := context.WithTimeout(context.Background(), 2*time.Second)
	go do(ctx)
	time.Sleep(5 * time.Second)
	fmt.Println("handler end...", time.Now())
}
func do(ctx context.Context) {
	i := 1
	for {
		time.Sleep(1 * time.Second)
		select {
		case <-ctx.Done():
			fmt.Println("done", time.Now())
			return
		default:
			fmt.Printf("work %d seconds: %v\n", i, time.Now())
		}
		i++
	}
}
func main() {
	fmt.Println("main start...")
	handler()
	fmt.Println("main end...")
}

程序輸出

main start...
handler start... 2023-06-10 10:51:17.0507657 +0800 CST m=+0.002568201
work 1 seconds: 2023-06-10 10:51:18.0618317 +0800 CST m=+1.013634201
done 2023-06-10 10:51:19.0620425 +0800 CST m=+2.013845001
handler end... 2023-06-10 10:51:22.0630702 +0800 CST m=+5.014872701
main end...

通過輸出可以看出來(lái),在2s超時(shí)之后,也就是done會(huì)主動(dòng)打印出來(lái),表明 cancel() 被主動(dòng)調(diào)用了。

以上就是Go語(yǔ)言并發(fā)之context標(biāo)準(zhǔn)庫(kù)的使用詳解的詳細(xì)內(nèi)容,更多關(guān)于Go語(yǔ)言context庫(kù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Golang在圖像中繪制矩形框的示例代碼

    Golang在圖像中繪制矩形框的示例代碼

    這篇文章主要介紹了Golang在圖像中繪制矩形框的示例代碼,文中有詳細(xì)的代碼示例供大家參考,具有一定的參考價(jià)值,需要的朋友可以參考下
    2008-08-08
  • 使用Go語(yǔ)言開發(fā)自動(dòng)化API測(cè)試工具詳解

    使用Go語(yǔ)言開發(fā)自動(dòng)化API測(cè)試工具詳解

    這篇文章主要為大家詳細(xì)介紹了如何使用Go語(yǔ)言開發(fā)自動(dòng)化API測(cè)試工具,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以參考下
    2024-03-03
  • 解決Golang小數(shù)float64在實(shí)際工程中加減乘除的精度問題

    解決Golang小數(shù)float64在實(shí)際工程中加減乘除的精度問題

    這篇文章主要介紹了解決Golang小數(shù)float64在實(shí)際工程中加減乘除的精度問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧
    2021-03-03
  • Go語(yǔ)言中sync包使用方法教程

    Go語(yǔ)言中sync包使用方法教程

    在Go語(yǔ)言的并發(fā)編程實(shí)踐中,性能優(yōu)化總是繞不開的話題,下面這篇文章主要介紹了Go語(yǔ)言中sync包使用方法的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-03-03
  • Go語(yǔ)言使用defer+recover解決panic導(dǎo)致程序崩潰的問題

    Go語(yǔ)言使用defer+recover解決panic導(dǎo)致程序崩潰的問題

    如果協(xié)程出現(xiàn)了panic,就會(huì)造成程序的崩潰,這時(shí)可以在goroutine中使用recover來(lái)捕獲panic,進(jìn)行處理,本文就詳細(xì)的介紹一下,感興趣的可以了解一下
    2021-09-09
  • golang網(wǎng)絡(luò)socket粘包問題的解決方法

    golang網(wǎng)絡(luò)socket粘包問題的解決方法

    這篇文章主要介紹了golang網(wǎng)絡(luò)socket粘包問題的解決方法,簡(jiǎn)單講述了socket粘包的定義并結(jié)合實(shí)例形式分析了Go語(yǔ)言解決粘包問題的方法,需要的朋友可以參考下
    2016-07-07
  • golang簡(jiǎn)單獲取上傳文件大小的實(shí)現(xiàn)代碼

    golang簡(jiǎn)單獲取上傳文件大小的實(shí)現(xiàn)代碼

    這篇文章主要介紹了golang簡(jiǎn)單獲取上傳文件大小的方法,涉及Go語(yǔ)言文件傳輸及文件屬性操作的相關(guān)技巧,需要的朋友可以參考下
    2016-07-07
  • 解決GOPATH在GOLAND中的坑

    解決GOPATH在GOLAND中的坑

    這篇文章主要介紹了解決GOPATH在GOLAND中的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧
    2020-12-12
  • Golang?range?slice?與range?array?之間的區(qū)別

    Golang?range?slice?與range?array?之間的區(qū)別

    這篇文章主要介紹了Golang?range?slice?與range?array?之間的區(qū)別,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-07-07
  • 深入了解Golang官方container/list原理

    深入了解Golang官方container/list原理

    在?Golang?的標(biāo)準(zhǔn)庫(kù)?container?中,包含了幾種常見的數(shù)據(jù)結(jié)構(gòu)的實(shí)現(xiàn),其實(shí)是非常好的學(xué)習(xí)材料,本文主要為大家介紹了container/list的原理與使用,感興趣的可以了解一下
    2023-08-08

最新評(píng)論