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

go語言解決并發(fā)問題小結(jié)

 更新時間:2024年05月20日 10:17:41   作者:snail_lie  
并發(fā)是GO最基本的功能了,但是在傳統(tǒng)的PHP中是比較困難的,如果不借助其它一些擴展的話,是做不到并發(fā)的,這篇文章主要介紹了go語言如何解決并發(fā)問題,需要的朋友可以參考下

一、選擇GO的原因

作為一個后端開發(fā),日常工作中接觸最多的兩門語言就是PHP和GO了。無可否認,PHP確實是最好的語言(手動狗頭哈哈),寫起來真的很舒爽,沒有任何心智負擔,字符串和整型壓根就不用區(qū)分,開發(fā)速度真的是比GO快很多?,F(xiàn)在工作中也還是有一些老項目在使用PHP,但21年之后的新項目基本上就都是用GO了。那為什么PHP那么香,還要轉(zhuǎn)戰(zhàn)使用GO呢,下面就給大家講解一下我們新項目從PHP轉(zhuǎn)GO的原因,有幾個比較重要的點:

1、PHP不能滿足我們的高并發(fā)業(yè)務,這是最主要的原因了,(PS:我這里所說的PHP是指官方的php-fpm模式下的開發(fā),是一個請求一個進程的那種模式,而不是類似于swoole常駐進程的那種。那么為什么不去使用swoole呢,當然也是有的,但swoole畢竟太小眾了,且之前有很多bug,使用起來心智負擔太高了),而我們部門所負責的是直播業(yè)務,每天都和高并發(fā)打交道啊,所以只能將目光轉(zhuǎn)向了并發(fā)小王子GO的懷抱。

2、GO語言當時在市面上很火,像騰訊、百度、滴滴、好未來這些大廠都在陸陸續(xù)續(xù)地從PHP轉(zhuǎn)向GO,這也是一個訊號吧,跟著大佬們走總不會錯。

3、GO語言的簡單簡潔,相比較于JAVA,上手是很快的(但真正學好還是沒那么容易的),我當時就學了兩個禮拜左右語法就跟著一起寫項目了。

二、GO解決的并發(fā)問題

說到并發(fā),是GO最基本的功能了,但是在傳統(tǒng)的PHP中是比較困難的,如果不借助其它一些擴展的話,是做不到并發(fā)的。舉個場景:每個用戶進入直播間,都要獲取很多信息,有版本服務信息、直播基礎信息、用戶信息、直播關聯(lián)權益信息、直播間信息統(tǒng)計等等。如果是PHP的寫法,就得按照下面串行的流程去做,這個接口耗時就是所有操作的時間之和,嚴重影響用戶體驗啊。

但如果換成GO去做這件事,那就非常清爽了,這個用戶請求耗時就只需要時間最長的那個操作耗時,如下圖:

那么我們?nèi)绾斡萌崿F(xiàn)這個并發(fā)邏輯呢?

方法1:使用sync.WaitGroup

//請求入口
func main() {
	var (
		VersionDetail, LiveDetail, UserDetail, EquityDetail, StatisticsDetail int
	)
	ctx := context.Background()
	GoNoErr(ctx, func() {
		VersionDetail = 1 //版本服務信息
		time.Sleep(1 * time.Second)
		fmt.Println("執(zhí)行第一個任務")
	}, func() {
		LiveDetail = 2 //直播基礎信息
		time.Sleep(2 * time.Second)
		fmt.Println("執(zhí)行第二個任務")
	}, func() {
		UserDetail = 3 //用戶信息
		time.Sleep(3 * time.Second)
		fmt.Println("執(zhí)行第三個任務")
	}, func() {
		EquityDetail = 4 //直播關聯(lián)權益信息
		time.Sleep(4 * time.Second)
		fmt.Println("執(zhí)行第四個任務")
	}, func() {
		StatisticsDetail = 5 //直播間信息統(tǒng)計
		time.Sleep(5 * time.Second)
		fmt.Println("執(zhí)行第五個任務")
	})
	fmt.Println(VersionDetail, LiveDetail, UserDetail, EquityDetail, StatisticsDetail)
}
//并發(fā)方法
func GoNoErr(ctx context.Context, functions ...func()) {
	var wg sync.WaitGroup
	for _, f := range functions {
		wg.Add(1)
		// 每個函數(shù)啟動一個協(xié)程
		go func(function func()) {
			function()
			wg.Done()
		}(f)
	}
	// 等待執(zhí)行完
	wg.Wait()
}

方法2:使用ErrGroup庫

//請求入口
func main() {
	var (
		VersionDetail, LiveDetail, UserDetail, EquityDetail, StatisticsDetail int
		err                                                                   error
	)
	ctx := context.Background()
	err = GoErr(ctx, func() error {
		VersionDetail = 1 //版本服務信息
		time.Sleep(1 * time.Second)
		fmt.Println("執(zhí)行第一個任務")
		return nil //返回實際執(zhí)行的錯誤
	}, func() error {
		LiveDetail = 2 //直播基礎信息
		time.Sleep(2 * time.Second)
		fmt.Println("執(zhí)行第二個任務")
		return nil //返回實際執(zhí)行的錯誤
	}, func() error {
		UserDetail = 3 //用戶信息
		time.Sleep(3 * time.Second)
		fmt.Println("執(zhí)行第三個任務")
		return nil //返回實際執(zhí)行的錯誤
	}, func() error {
		EquityDetail = 4 //直播關聯(lián)權益信息
		time.Sleep(4 * time.Second)
		fmt.Println("執(zhí)行第四個任務")
		return nil //返回實際執(zhí)行的錯誤
	}, func() error {
		StatisticsDetail = 5 //直播間信息統(tǒng)計
		time.Sleep(5 * time.Second)
		fmt.Println("執(zhí)行第五個任務")
		return nil //返回實際執(zhí)行的錯誤
	})
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(VersionDetail, LiveDetail, UserDetail, EquityDetail, StatisticsDetail)
}
func GoErr(ctx context.Context, functions ...func() error) error {
	var eg errgroup.Group
	for i := range functions { 
		f := functions[i]  //請注意這里的寫法,下面有講解
		eg.Go(func() (err error) {
			err = f()
			if err != nil {
				//記日志
			}
			return err
		})
	}
	// 等待執(zhí)行完
	return eg.Wait()
}

上面就是使用ErrGroup庫的并發(fā)執(zhí)行任務的方法,可以直接拿來使用,ErrGroup這是GO官方提供的一個同步擴展庫可以很好地將?個通?的?任務拆成?個?任務并發(fā)執(zhí)?。

上面有一點需要特別注意的寫法,就是下面這段代碼的寫法,寫法1:

for i := range functions { 
		f := functions[i]  
		eg.Go(func() (err error) {
			err = f()

也可以這樣寫,寫法2:

for _, f := range functions { 
		fs := f  
		eg.Go(func() (err error) {
			err = fs()

但如果這樣寫就會有問題,寫法3:

for _, f := range functions { 
		eg.Go(func() (err error) {
			err = f()

你們可以改一下,實際跑一下。會發(fā)現(xiàn) (寫法3) 會出現(xiàn)類似這樣的錯誤結(jié)果

正確預期的結(jié)果(寫法1、寫法2)應該是這樣的

這是因為在 Go 語言中,當使用閉包(匿名函數(shù))時,如果閉包引用了外部的變量,閉包實際上會捕獲這些變量的引用。在循環(huán)中創(chuàng)建閉包時,如果直接將循環(huán)變量作為閉包的參數(shù)或在閉包中引用該變量,會導致所有生成的閉包都引用相同的變量,即最后一次迭代的值。

為了避免這個問題,常見的做法是在循環(huán)內(nèi)部創(chuàng)建一個新的變量,將循環(huán)變量的值賦給這個新變量,然后在閉包中引用該新變量。這樣,每次循環(huán)迭代都會創(chuàng)建一個新的變量,閉包捕獲的是不同的變量引用,而不是相同變量的引用。

在給定的代碼中,fs := f 就是為了創(chuàng)建一個新的變量 f,并將循環(huán)變量 f 的值賦給它。這樣,在閉包中就可以安全地引用這個新變量 f,而不會受到循環(huán)迭代的影響。這個技巧非常有用,可以在循環(huán)中創(chuàng)建多個獨立的閉包,并確保它們捕獲的是預期的變量值,而不會受到循環(huán)迭代的干擾

當然,還有一些第三方庫也實現(xiàn)了上面的并發(fā)分組操作,大家感興趣的可以去GitHub上看看,但功能和實現(xiàn)基本都大同小異。以上就是GO并發(fā)的基礎,將一個父任務拆分成多個子任務去執(zhí)行,提高程序的并發(fā)度,節(jié)省程序耗時。我們平時在工作中,兩種方法都可以直接拿來使用,可以說這兩個GO并發(fā)方法幾乎貫穿了我的GO職業(yè)生涯,也是最基礎最實用的并發(fā)操作方法。

到此這篇關于go語言如何解決并發(fā)問題的文章就介紹到這了,更多相關go語言并發(fā)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • golang?db事務的統(tǒng)一封裝的實現(xiàn)

    golang?db事務的統(tǒng)一封裝的實現(xiàn)

    這篇文章主要介紹了golang db事務的統(tǒng)一封裝的實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • golang:json 反序列化的[]和nil操作

    golang:json 反序列化的[]和nil操作

    這篇文章主要介紹了golang:json 反序列化的[]和nil操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • 使用go mod導入本地自定義包問題

    使用go mod導入本地自定義包問題

    這篇文章主要介紹了使用go mod導入本地自定義包問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Go net/http的簡單使用小結(jié)

    Go net/http的簡單使用小結(jié)

    Go語言提供了一個功能豐富的net/http包,它提供了客戶端和服務端的實現(xiàn),使得我們可以比較輕易的創(chuàng)建http服務,下面就來介紹一下Go net/http使用,感興趣的可以了解一下
    2025-07-07
  • go?module化?import?調(diào)用本地模塊?tidy的方法

    go?module化?import?調(diào)用本地模塊?tidy的方法

    這篇文章主要介紹了go?module化?import?調(diào)用本地模塊?tidy的相關知識,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-09-09
  • Go語言死鎖與goroutine泄露問題的解決

    Go語言死鎖與goroutine泄露問題的解決

    最近在工作中使用golang編程,今天的文章給大家分享一下Go語言死鎖與goroutine泄露問題,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • Go語言利用aicli實現(xiàn)輕松調(diào)用DeepSeek和ChatGPT

    Go語言利用aicli實現(xiàn)輕松調(diào)用DeepSeek和ChatGPT

    這篇文章主要為大家介紹了一款用Go語言編寫的AI助手客戶端庫——aicli,該庫不僅支持ChatGPT,還集成了DeepSeek,感興趣的小伙伴可以了解一下
    2025-03-03
  • Go?sort.Interface的基本使用

    Go?sort.Interface的基本使用

    本文主要介紹了Go?sort.Interface的基本使用,及對不同類型的數(shù)據(jù)進行排序,包括字符串切片、結(jié)構(gòu)體切片等,并提供了具體示例,具有一定的參考價值,感興趣的可以了解一下
    2026-04-04
  • Go語言學習之操作MYSQL實現(xiàn)CRUD

    Go語言學習之操作MYSQL實現(xiàn)CRUD

    Go官方提供了database包,database包下有sql/driver。該包用來定義操作數(shù)據(jù)庫的接口,這保證了無論使用哪種數(shù)據(jù)庫,操作方式都是相同的。本文就來和大家聊聊Go語言如何操作MYSQL實現(xiàn)CRUD,希望對大家有所幫助
    2023-02-02
  • 一文了解Go語言的并發(fā)特性

    一文了解Go語言的并發(fā)特性

    本文主要介紹了一文了解Go語言的并發(fā)特性,通過輕量級線程、通道及選擇語句,使得并發(fā)編程變得既簡單又高效,下面就來具體了解一下如何使用,感興趣的可以了解一下
    2024-02-02

最新評論

高平市| 图木舒克市| 饶阳县| 连南| 南康市| 永善县| 叶城县| 呼伦贝尔市| 永丰县| 邵武市| 镇平县| 安化县| 江油市| 古丈县| 紫云| 茶陵县| 天门市| 天水市| 东平县| 峨眉山市| 韶山市| 鹰潭市| 泰兴市| 申扎县| 镇平县| 高清| 丹东市| 米林县| 高邮市| 桃园市| 南乐县| 汽车| 项城市| 宝应县| 靖州| 禹城市| 台中市| 南漳县| 军事| 那坡县| 广德县|