女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

go語(yǔ)言如何解決并發(fā)問(wèn)題

馬哥Linux運(yùn)維 ? 來(lái)源:博客園snail_lie ? 2024-10-23 13:38 ? 次閱讀

一、選擇GO的原因

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

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

2、GO語(yǔ)言當(dāng)時(shí)在市面上很火,像騰訊、百度、滴滴、好未來(lái)這些大廠都在陸陸續(xù)續(xù)地從PHP轉(zhuǎn)向GO,這也是一個(gè)訊號(hào)吧,跟著大佬們走總不會(huì)錯(cuò)。

3、GO語(yǔ)言的簡(jiǎn)單簡(jiǎn)潔,相比較于JAVA,上手是很快的(但真正學(xué)好還是沒(méi)那么容易的),我當(dāng)時(shí)就學(xué)了兩個(gè)禮拜左右語(yǔ)法就跟著一起寫(xiě)項(xiàng)目了。

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

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

e9cda7d2-90f6-11ef-a511-92fbcf53809c.png

但如果換成GO去做這件事,那就非常清爽了,這個(gè)用戶請(qǐng)求耗時(shí)就只需要時(shí)間最長(zhǎng)的那個(gè)操作耗時(shí),如下圖:

e9e5d6ea-90f6-11ef-a511-92fbcf53809c.png

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

方法1:使用sync.WaitGroup

//請(qǐng)求入口
func main() {
var (
VersionDetail, LiveDetail, UserDetail, EquityDetail, StatisticsDetail int
)
ctx := context.Background()
GoNoErr(ctx, func() {
VersionDetail = 1 //版本服務(wù)信息
time.Sleep(1 * time.Second)
fmt.Println("執(zhí)行第一個(gè)任務(wù)")
}, func() {
LiveDetail = 2 //直播基礎(chǔ)信息
time.Sleep(2 * time.Second)
fmt.Println("執(zhí)行第二個(gè)任務(wù)")
}, func() {
UserDetail = 3 //用戶信息
time.Sleep(3 * time.Second)
fmt.Println("執(zhí)行第三個(gè)任務(wù)")
}, func() {
EquityDetail = 4 //直播關(guān)聯(lián)權(quán)益信息
time.Sleep(4 * time.Second)
fmt.Println("執(zhí)行第四個(gè)任務(wù)")
}, func() {
StatisticsDetail = 5 //直播間信息統(tǒng)計(jì)
time.Sleep(5 * time.Second)
fmt.Println("執(zhí)行第五個(gè)任務(wù)")
})
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)
// 每個(gè)函數(shù)啟動(dòng)一個(gè)協(xié)程
go func(function func()) {
function()
wg.Done()
}(f)
}
// 等待執(zhí)行完
wg.Wait()
}

方法2:使用ErrGroup庫(kù)

//請(qǐng)求入口
func main() {
var (
VersionDetail, LiveDetail, UserDetail, EquityDetail, StatisticsDetail int
err                                                                   error
)
ctx := context.Background()
err = GoErr(ctx, func() error {
VersionDetail = 1 //版本服務(wù)信息
time.Sleep(1 * time.Second)
fmt.Println("執(zhí)行第一個(gè)任務(wù)")
return nil //返回實(shí)際執(zhí)行的錯(cuò)誤
}, func() error {
LiveDetail = 2 //直播基礎(chǔ)信息
time.Sleep(2 * time.Second)
fmt.Println("執(zhí)行第二個(gè)任務(wù)")
return nil //返回實(shí)際執(zhí)行的錯(cuò)誤
}, func() error {
UserDetail = 3 //用戶信息
time.Sleep(3 * time.Second)
fmt.Println("執(zhí)行第三個(gè)任務(wù)")
return nil //返回實(shí)際執(zhí)行的錯(cuò)誤
}, func() error {
EquityDetail = 4 //直播關(guān)聯(lián)權(quán)益信息
time.Sleep(4 * time.Second)
fmt.Println("執(zhí)行第四個(gè)任務(wù)")
return nil //返回實(shí)際執(zhí)行的錯(cuò)誤
}, func() error {
StatisticsDetail = 5 //直播間信息統(tǒng)計(jì)
time.Sleep(5 * time.Second)
fmt.Println("執(zhí)行第五個(gè)任務(wù)")
return nil //返回實(shí)際執(zhí)行的錯(cuò)誤
})
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]  //請(qǐng)注意這里的寫(xiě)法,下面有講解
eg.Go(func() (err error) {
err = f()
if err != nil {
//記日志
}
return err
})
}
// 等待執(zhí)行完
return eg.Wait()
}

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

上面有一點(diǎn)需要特別注意的寫(xiě)法,就是下面這段代碼的寫(xiě)法,寫(xiě)法1:

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

也可以這樣寫(xiě),寫(xiě)法2:

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

但如果這樣寫(xiě)就會(huì)有問(wèn)題,寫(xiě)法3:

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

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

ea103a84-90f6-11ef-a511-92fbcf53809c.png

正確預(yù)期的結(jié)果(寫(xiě)法1、寫(xiě)法2)應(yīng)該是這樣的

ea234642-90f6-11ef-a511-92fbcf53809c.png

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

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

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

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

一個(gè)人可以被毀滅,但不可以被打敗。

鏈接:https://www.cnblogs.com/lmz-blogs/p/18200946

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4367

    瀏覽量

    64156
  • 進(jìn)程
    +關(guān)注

    關(guān)注

    0

    文章

    206

    瀏覽量

    14211
  • go語(yǔ)言
    +關(guān)注

    關(guān)注

    1

    文章

    158

    瀏覽量

    9285

原文標(biāo)題:go高并發(fā)之路——go語(yǔ)言如何解決并發(fā)問(wèn)題

文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    Go語(yǔ)言簡(jiǎn)介和安裝方法

    Go 又稱 Golang ,是 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 開(kāi)發(fā)的一種靜態(tài)強(qiáng)類型、編譯型語(yǔ)言Go 語(yǔ)言語(yǔ)法與
    發(fā)表于 07-19 16:33 ?683次閱讀

    三十分鐘入門(mén)基礎(chǔ)Go Java小子版

    語(yǔ)法與 C 相近,但功能上有:內(nèi)存安全,GC,結(jié)構(gòu)形態(tài)及 CSP-style 并發(fā)計(jì)算。 適用范圍 本篇文章適用于學(xué)習(xí)過(guò)其他面向?qū)ο?b class='flag-5'>語(yǔ)言(Java、Php),但沒(méi)有學(xué)過(guò)Go語(yǔ)言的初學(xué)者
    的頭像 發(fā)表于 08-12 14:32 ?934次閱讀
    三十分鐘入門(mén)基礎(chǔ)<b class='flag-5'>Go</b> Java小子版

    Go語(yǔ)言開(kāi)發(fā)有什么優(yōu)勢(shì)?怎么學(xué)?

    的方式全面的闡述Go在高并發(fā)、大流量方面的應(yīng)用,課程中采用的四個(gè)項(xiàng)目全部來(lái)自大公司實(shí)實(shí)在在的線上案例,并不是通過(guò)簡(jiǎn)化的、閹割過(guò)的項(xiàng)目。可以學(xué)習(xí)到Go語(yǔ)言理論與應(yīng)用的最佳實(shí)踐,高
    發(fā)表于 12-19 16:08

    Go開(kāi)發(fā)語(yǔ)言的優(yōu)勢(shì)在哪里?

    Go語(yǔ)言是谷歌發(fā)布的第二款開(kāi)源編程語(yǔ)言,可以在不損失應(yīng)用程序性能的情況下降低代碼的復(fù)雜性,并專門(mén)針對(duì)多處理器系統(tǒng)應(yīng)用程序的編程進(jìn)行了優(yōu)化,開(kāi)發(fā)速度極快,可以與C或C++媲美,而且更加安全、支持并行
    發(fā)表于 03-22 15:04

    何解決stm32 485串口數(shù)據(jù)的收發(fā)問(wèn)題?

    何解決stm32 485串口數(shù)據(jù)的收發(fā)問(wèn)題?
    發(fā)表于 12-13 06:50

    Go語(yǔ)言及Beego框架環(huán)境搭建相關(guān)資料推薦

    就完成了。  天生支持并發(fā),可以充分的利用多核,很容易實(shí)現(xiàn)并發(fā)。  25個(gè)關(guān)鍵字,但是表達(dá)能力很強(qiáng)大,幾乎支持大多數(shù)你在其他語(yǔ)言見(jiàn)過(guò)的特性:繼承、重載、對(duì)象等。  內(nèi)置強(qiáng)大的工具,Go
    發(fā)表于 10-17 16:57

    網(wǎng)易有道CEO周楓推薦Go語(yǔ)言并介紹Go語(yǔ)言的3個(gè)優(yōu)點(diǎn)

    網(wǎng)易有道CEO周楓推薦Go語(yǔ)言。他認(rèn)為Go很好地繼承了C語(yǔ)言靈活、簡(jiǎn)單有效的思想;Go有很高的生產(chǎn)效率;
    的頭像 發(fā)表于 01-31 14:11 ?5371次閱讀

    詳析Java線程進(jìn)程的并發(fā)問(wèn)

    并發(fā)問(wèn)題發(fā)生的前提條件一定是資源共享,這里的資源一般指的是數(shù)據(jù),共享指的是多線程之間共享。
    的頭像 發(fā)表于 07-07 11:44 ?2492次閱讀

    詳解GO語(yǔ)言的趨勢(shì)與使用情況

    Go 語(yǔ)言簡(jiǎn)單易學(xué)、性能優(yōu)良。JetBrains Blog 發(fā)布了Go 語(yǔ)言的調(diào)查報(bào)告,看看GO 語(yǔ)言
    的頭像 發(fā)表于 03-17 11:05 ?3218次閱讀

    Go語(yǔ)言憑借什么成為云原生第一語(yǔ)言的?

    偶然看到有人說(shuō), Go 語(yǔ)言目前的火爆可能就是曇花一現(xiàn)而已。這個(gè)觀點(diǎn)我當(dāng)然是不認(rèn)同的。 近幾年,關(guān)于 Go 與 Java 還有 C 的對(duì)比和討論愈演愈烈,但不可否認(rèn)的是,在十年多的時(shí)間里,Go
    的頭像 發(fā)表于 04-22 10:15 ?3374次閱讀
    <b class='flag-5'>Go</b><b class='flag-5'>語(yǔ)言</b>憑借什么成為云原生第一<b class='flag-5'>語(yǔ)言</b>的?

    golang并發(fā)機(jī)制和其他語(yǔ)言在實(shí)現(xiàn)上有什么不同

    golang 并發(fā)機(jī)制和其他語(yǔ)言在實(shí)現(xiàn)上有什么不同?為什么能做到高效快速?本文做了詳細(xì)介紹。 由于對(duì)普通語(yǔ)法的介紹網(wǎng)上資源極多,Go 官方的上手指南 A Tour of Go: htt
    的頭像 發(fā)表于 07-29 16:35 ?1594次閱讀
    golang<b class='flag-5'>并發(fā)</b>機(jī)制和其他<b class='flag-5'>語(yǔ)言</b>在實(shí)現(xiàn)上有什么不同

    go語(yǔ)言枚舉類型怎么用

    go 語(yǔ)言枚舉類型是這么用的?在什么場(chǎng)景下會(huì)用到枚舉?本文對(duì) go 語(yǔ)言枚舉做了詳細(xì)講解。 枚舉,是一種重要的數(shù)據(jù)類型,由一組鍵值對(duì)組成,通常用來(lái)在編程
    的頭像 發(fā)表于 09-02 09:43 ?5412次閱讀

    帶你了解go語(yǔ)言中的閉包

    ? 【 導(dǎo)讀】什么是閉包? 什么場(chǎng)景下會(huì)用閉包 ? 本文對(duì) go 語(yǔ)言中的閉包做了詳細(xì)介紹。 閉包是由函數(shù)及其相關(guān)引用環(huán)境組合而成的實(shí)體(即:閉包=函數(shù)+引用環(huán)境)。 Go中的閉包 閉包是函數(shù)式
    的頭像 發(fā)表于 11-02 15:27 ?2642次閱讀

    Go并發(fā)模型的實(shí)現(xiàn)原理

    Go語(yǔ)言是為并發(fā)而生的語(yǔ)言Go語(yǔ)言是為數(shù)不多的在語(yǔ)言
    的頭像 發(fā)表于 04-15 08:49 ?1564次閱讀

    go語(yǔ)言中怎么使用HTTP代理

    go語(yǔ)言中怎么使用HTTP代理。
    的頭像 發(fā)表于 09-01 14:41 ?2607次閱讀