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

淺析Golang開發(fā)中g(shù)oroutine的正確使用姿勢

 更新時間:2024年03月10日 16:16:39   作者:飛翔碼農(nóng)  
很多初級的Gopher在學習了goroutine之后,在項目中其實使用率不高,所以這篇文章小編主要來帶大家深入了解一下goroutine的常見使用方法,希望對大家有所幫助

很多初級的Gopher在學習了goroutine之后,在項目中其實使用率不高,尤其一些跨語言過來的人,對并發(fā)編程理解不深入,可能很多人只知道go func(),或者掌控不夠,謹慎一些,盡量少使用或者不使用,用的話就是go func(),主要列一下我們這邊的主要使用方法。

goroutine在項目中的使用方法

看一下樣例代碼,實際上,我們生產(chǎn)環(huán)境中就是這么使用的。

package logic

import (
    "context"
    "fmt"
    "sync"
    "time"
)

type UserData struct {
	Age     int
	Name    string
	Postion string
}

type ServerLogic struct {
	ctx    context.Context
	cancel func()
	waiter sync.WaitGroup
	ch     chan UserData
}

func NewServerLogic(logCtx *context.Context, worker int, queue int) *ServerLogic {
	logic := &ServerLogic{}
	logic.InitWorker(worker, queue)
	return logic
}

func (this *ServerLogic) InitWorker(workers int, queue int) {
	this.ch = make(chan UserData, queue)
	this.ctx, this.cancel = context.WithCancel(context.Background())
	this.waiter.Add(workers)
	for i := 0; i < workers; i++ {
		go this.Proc()
	}
}

func (this *ServerLogic) Proc() {
	defer this.waiter.Done()
	for {
		select {
		case t := <-this.ch:
			this.Dothing(t)
		case <-this.ctx.Done():
			return
		}
	}
}

func (this *ServerLogic) Dothing(data UserData) error {
	//do code
    time.Sleep(time.Second*30)
	return nil
}

func (this *ServerLogic) Close() {
	this.cancel()
    this.waiter.Wait()
}

func (this *ServerLogic) PutData(user UserData) error {
    select {
    case this.ch<-user:
        return nil
	default:
		return fmt.Errorf("queue overflow")
    }
}

如果有人想直接使用的話,只需要把UserData struct換成自己的請求數(shù)據(jù),把Dothing里面的代碼換成讓goroutine多任務(wù)執(zhí)行的代碼就可以在自己的項目中使用了。

PutData有請求數(shù)據(jù)就放入channel,每個goroutine不停的循環(huán)從channel里面取數(shù)據(jù),取到數(shù)據(jù)之后就執(zhí)行相應的邏輯流程,可以看到整體的調(diào)度都是channel來控制的,通過channel的通信來傳遞數(shù)據(jù)。

不要通過共享內(nèi)存來通信,要通過通信來共享內(nèi)存

看看大概的代碼分析

  • InitWorker的時候會創(chuàng)建queue個channl,再創(chuàng)建workers個goroutine,執(zhí)行g(shù)o Proc()
  • Proc方法,里面有for的無限循環(huán),不停從步驟1里面創(chuàng)建的channl里面獲取UserData數(shù)據(jù),一旦獲取數(shù)據(jù)成功,就會帶著UserData數(shù)據(jù)去執(zhí)行Dothing方法。需要注意的是,這是workers個goroutine都在執(zhí)行Proc
  • Dothing方法,就是讓某一個goroutine拿到UserData數(shù)據(jù)去處理數(shù)據(jù),執(zhí)行邏輯
  • Close方法,給所有的goroutine發(fā)送關(guān)閉的信號,channl里面不在有數(shù)據(jù)寫入,waiter.Wait()等待現(xiàn)有的channel里面數(shù)據(jù)被消費完,goroutine就執(zhí)行完畢退出。
  • PutData方法,就是把請求的數(shù)據(jù)交給goroutine去執(zhí)行。具體的做法,是把數(shù)據(jù) 塞到channl隊列里面,如果queue個channl隊列已滿,就拋出溢出錯誤。

當然了PutData也可以等待channl隊列里面的數(shù)據(jù)被Proc拿出,然后空出位置再塞數(shù)據(jù)到channl隊列。

func (this *ServerLogic) PutData(user UserData) error {
	timer := time.NewTimer(3*time.Second)
	select {
    case this.ch<-user:
        return nil
	case <-timer.C:
		return fmt.Errorf("put timeout")
    }
}

加一個超時器,總不能等到天荒地老把,如果超過三秒,仍然沒有空出channl位置,現(xiàn)有的隊列還沒有消費完,就拋出塞數(shù)據(jù)超時的錯誤.

看一下樣例的使用的代碼

package main

import (
	context2 "context"
	"fmt"
	"test/logic"
)

func main() {
	context := context2.Background()
	server := logic.NewServerLogic(&context, 1, 2)
	rt1 := server.PutData(logic.UserData{
		Age:     11,
		Name:    "test1",
		Postion: "golang",
	})
	fmt.Println(rt1)
	rt2 := server.PutData(logic.UserData{
		Age:     12,
		Name:    "test2",
		Postion: "golang",
	})
	fmt.Println(rt2)
	rt3 := server.PutData(logic.UserData{
		Age:     13,
		Name:    "test3",
		Postion: "golang",
	})
	fmt.Println(rt3)

	server.Close()
	fmt.Println("end")
}

等待了大概三十多秒之后的結(jié)果,打印結(jié)果其實跟預想的是一樣的。

<nil>
<nil>
queue overflow
end

NewServerLogic(&context, 1, 2)代碼中,我們要求創(chuàng)建了1個goroutine,大小為2的channl隊列。
所以第一個PutData和第二個PutData是塞數(shù)據(jù)成功的。等到第三次PutData的時候,因為我們channl隊列的大小是2,已經(jīng)被占滿了,所以第三次就會提示溢出錯誤。

使用goroutine另一種方法

我看項目中還有一些其他人的使用方法,區(qū)別只是退出的時候沒有使用context的cancel方法,而是使用了channel去通知退出goroutine,內(nèi)部的原理其實是一樣的??匆幌孪旅娴拇a。

func(this *ServerLogic)InitWorker(workers int, queue int)
{
    this.quit = make(chan bool)
    this.ch = make(chan UserData, queue)
    this.waiter.Add(workers)
    for i :=0;i< workers; i++ {
        go this.Proc()
    }
}

func(this *ServerLogic)Proc()
{
    defer this.waiter.Done()
    for {
        select {
            case t := ←this.ch:
            this.Dothing(t)
            case ←this.quit:
                 return   
        }
    }
}

func(this *ServerLogic)Close(){
    close(this.quit)
    this.waiter.Wait()
}

只有關(guān)閉這里是不一樣的,其他的基本一致。執(zhí)行退出的時候在Close()方法中,close(this.quit)會給quit channel寫入數(shù)據(jù),Proc()方法會循環(huán)從channel和quit里面取數(shù)據(jù),一旦從this.quit里面取出了數(shù)據(jù),說明系統(tǒng)讓關(guān)閉goroutine,然后Proc方法就終止。

go func()行不行

有人說,扯這么多,為啥go func()不行,我在項目里面使用go func()運行的好好,而且golang的HTTP庫里也是使用的go c.serve(ctx)。

我的理解是主要看使用場景,如果你的服務(wù)對結(jié)果要求不是100%的成功,對并發(fā)的要求很高,那就可以使用go func(),go c.serve(ctx)也是類似,TCP本身就是不可靠的連接,HTTP也允許有極少量的失敗狀態(tài)。

如果你的服務(wù)里面只是想讓多個goroutine處理你的數(shù)據(jù),不希望這個goroutine太多影響你的主干服務(wù),或者你為了提高數(shù)據(jù)處理效率,想讓多個goroutine去請求第三方的服務(wù),這樣的話,就應該創(chuàng)建若干個goroutine去并發(fā)處理你的任務(wù),也不建議直接go func(),goroutine數(shù)量不可控,會影響其他的主干服務(wù)或者占用服務(wù)器資源,如果請求第三方的服務(wù),可能會因為并發(fā)太高被限制,或者把第三方服務(wù)打掛。我們就遇到過這種情況。

總之,使用場景很重要,不是一概而論的。

到此這篇關(guān)于淺析Golang開發(fā)中g(shù)oroutine的正確使用姿勢 的文章就介紹到這了,更多相關(guān)Go goroutine內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家

相關(guān)文章

  • GO文件創(chuàng)建及讀寫操作示例詳解

    GO文件創(chuàng)建及讀寫操作示例詳解

    這篇文章主要為大家介紹了GO文件創(chuàng)建及讀寫操作示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪
    2022-04-04
  • go的defer和閉包示例說明(非內(nèi)部實現(xiàn))

    go的defer和閉包示例說明(非內(nèi)部實現(xiàn))

    這篇文章主要為大家介紹了go的defer和閉包示例說明(非內(nèi)部實現(xiàn)),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-08-08
  • 一百行Golang代碼實現(xiàn)簡單并發(fā)聊天室

    一百行Golang代碼實現(xiàn)簡單并發(fā)聊天室

    這篇文章主要為大家詳細介紹了一百行Golang代碼如何實現(xiàn)簡單并發(fā)聊天室,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • gRPC超時攔截器實現(xiàn)示例

    gRPC超時攔截器實現(xiàn)示例

    這篇文章主要為大家介紹了gRPC超時攔截器實現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • Go 語言使用互斥鎖進行同步

    Go 語言使用互斥鎖進行同步

    我們可以利用互斥鎖來保護代碼中的關(guān)鍵部分,從而確保每次只能有一個 goroutine 訪問共享資源,這樣就能避免競爭條件的問題,感興趣的可以了解一下
    2026-05-05
  • Go中的新增對模糊測試的支持

    Go中的新增對模糊測試的支持

    這篇文章主要為大家介紹了Go中的新增對模糊測試的支持,文中還包含了一些功能實驗性測試分析有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-03-03
  • 基于Go語言實現(xiàn)冒泡排序算法

    基于Go語言實現(xiàn)冒泡排序算法

    冒泡排序是交換排序中最簡單的一種算法。這篇文章將利用Go語言實現(xiàn)冒泡排序算法,文中的示例代碼講解詳細,對學習Go語言有一定的幫助,需要的可以參考一下
    2022-12-12
  • Go中g(shù)routine通信與context控制實例詳解

    Go中g(shù)routine通信與context控制實例詳解

    隨著context包的引入,標準庫中很多接口因此加上了context參數(shù),下面這篇文章主要給大家介紹了關(guān)于Go中g(shù)routine通信與context控制的相關(guān)資料,需要的朋友可以參考下
    2022-02-02
  • 一文詳解go同步協(xié)程的必備工具WaitGroup

    一文詳解go同步協(xié)程的必備工具WaitGroup

    這篇文章主要為大家介紹了一文詳解go同步協(xié)程的必備工具WaitGroup使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • goland中導包報紅和go mod問題

    goland中導包報紅和go mod問題

    這篇文章主要介紹了goland中導包報紅和go mod問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03

最新評論

阳曲县| 淅川县| 河东区| 大英县| 木里| 芜湖县| 吉隆县| 扎囊县| 武邑县| 仪陇县| 平遥县| 莱西市| 德州市| 同德县| 宣恩县| 澄迈县| 阿合奇县| 普洱| 绥阳县| 桃源县| 当雄县| 新化县| 乐安县| 连州市| 双流县| 舒兰市| 明水县| 乳源| 阿勒泰市| 黎平县| 德化县| 陇川县| 吴江市| 桂平市| 平果县| 长丰县| 东莞市| 垣曲县| 鄢陵县| 乐亭县| 红原县|