在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

go語言如何解決并發問題

馬哥Linux運維 ? 來源:博客園snail_lie ? 2024-10-23 13:38 ? 次閱讀

一、選擇GO的原因

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

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

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

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

二、GO解決的并發問題

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

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

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

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

那么我們如何用去實現這個并發邏輯呢?

方法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("執行第一個任務")
}, func() {
LiveDetail = 2 //直播基礎信息
time.Sleep(2 * time.Second)
fmt.Println("執行第二個任務")
}, func() {
UserDetail = 3 //用戶信息
time.Sleep(3 * time.Second)
fmt.Println("執行第三個任務")
}, func() {
EquityDetail = 4 //直播關聯權益信息
time.Sleep(4 * time.Second)
fmt.Println("執行第四個任務")
}, func() {
StatisticsDetail = 5 //直播間信息統計
time.Sleep(5 * time.Second)
fmt.Println("執行第五個任務")
})
fmt.Println(VersionDetail, LiveDetail, UserDetail, EquityDetail, StatisticsDetail)
}

//并發方法
func GoNoErr(ctx context.Context, functions ...func()) {
var wg sync.WaitGroup
for _, f := range functions {
wg.Add(1)
// 每個函數啟動一個協程
go func(function func()) {
function()
wg.Done()
}(f)
}
// 等待執行完
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("執行第一個任務")
return nil //返回實際執行的錯誤
}, func() error {
LiveDetail = 2 //直播基礎信息
time.Sleep(2 * time.Second)
fmt.Println("執行第二個任務")
return nil //返回實際執行的錯誤
}, func() error {
UserDetail = 3 //用戶信息
time.Sleep(3 * time.Second)
fmt.Println("執行第三個任務")
return nil //返回實際執行的錯誤
}, func() error {
EquityDetail = 4 //直播關聯權益信息
time.Sleep(4 * time.Second)
fmt.Println("執行第四個任務")
return nil //返回實際執行的錯誤
}, func() error {
StatisticsDetail = 5 //直播間信息統計
time.Sleep(5 * time.Second)
fmt.Println("執行第五個任務")
return nil //返回實際執行的錯誤
})
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
})
}
// 等待執行完
return eg.Wait()
}

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

上面有一點需要特別注意的寫法,就是下面這段代碼的寫法,寫法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()

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

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

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

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

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

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

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

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

一個人可以被毀滅,但不可以被打敗。

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

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 函數
    +關注

    關注

    3

    文章

    4346

    瀏覽量

    62972
  • 進程
    +關注

    關注

    0

    文章

    204

    瀏覽量

    13995
  • go語言
    +關注

    關注

    1

    文章

    158

    瀏覽量

    9089

原文標題:go高并發之路——go語言如何解決并發問題

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    Go語言簡介和安裝方法

    Go 又稱 Golang ,是 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 開發的一種靜態強類型、編譯型語言。Go 語言語法與
    發表于 07-19 16:33 ?586次閱讀

    三十分鐘入門基礎Go Java小子版

    語法與 C 相近,但功能上有:內存安全,GC,結構形態及 CSP-style 并發計算。 適用范圍 本篇文章適用于學習過其他面向對象語言(Java、Php),但沒有學過Go語言的初學者
    的頭像 發表于 08-12 14:32 ?786次閱讀
    三十分鐘入門基礎<b class='flag-5'>Go</b> Java小子版

    Go語言開發有什么優勢?怎么學?

    的方式全面的闡述Go在高并發、大流量方面的應用,課程中采用的四個項目全部來自大公司實實在在的線上案例,并不是通過簡化的、閹割過的項目??梢詫W習到Go語言理論與應用的最佳實踐,高
    發表于 12-19 16:08

    Go開發語言的優勢在哪里?

    Go語言是谷歌發布的第二款開源編程語言,可以在不損失應用程序性能的情況下降低代碼的復雜性,并專門針對多處理器系統應用程序的編程進行了優化,開發速度極快,可以與C或C++媲美,而且更加安全、支持并行
    發表于 03-22 15:04

    何解決stm32 485串口數據的收發問題?

    何解決stm32 485串口數據的收發問題?
    發表于 12-13 06:50

    Go語言及Beego框架環境搭建相關資料推薦

    就完成了。  天生支持并發,可以充分的利用多核,很容易實現并發?! ?5個關鍵字,但是表達能力很強大,幾乎支持大多數你在其他語言見過的特性:繼承、重載、對象等。  內置強大的工具,Go
    發表于 10-17 16:57

    網易有道CEO周楓推薦Go語言并介紹Go語言的3個優點

    網易有道CEO周楓推薦Go語言。他認為Go很好地繼承了C語言靈活、簡單有效的思想;Go有很高的生產效率;
    的頭像 發表于 01-31 14:11 ?5242次閱讀

    詳析Java線程進程的并發問

    并發問題發生的前提條件一定是資源共享,這里的資源一般指的是數據,共享指的是多線程之間共享。
    的頭像 發表于 07-07 11:44 ?2409次閱讀

    詳解GO語言的趨勢與使用情況

    Go 語言簡單易學、性能優良。JetBrains Blog 發布了Go 語言的調查報告,看看GO 語言
    的頭像 發表于 03-17 11:05 ?3084次閱讀

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

    偶然看到有人說, Go 語言目前的火爆可能就是曇花一現而已。這個觀點我當然是不認同的。 近幾年,關于 Go 與 Java 還有 C 的對比和討論愈演愈烈,但不可否認的是,在十年多的時間里,Go
    的頭像 發表于 04-22 10:15 ?3229次閱讀
    <b class='flag-5'>Go</b><b class='flag-5'>語言</b>憑借什么成為云原生第一<b class='flag-5'>語言</b>的?

    golang并發機制和其他語言在實現上有什么不同

    golang 并發機制和其他語言在實現上有什么不同?為什么能做到高效快速?本文做了詳細介紹。 由于對普通語法的介紹網上資源極多,Go 官方的上手指南 A Tour of Go: htt
    的頭像 發表于 07-29 16:35 ?1493次閱讀
    golang<b class='flag-5'>并發</b>機制和其他<b class='flag-5'>語言</b>在實現上有什么不同

    go語言枚舉類型怎么用

    go 語言枚舉類型是這么用的?在什么場景下會用到枚舉?本文對 go 語言枚舉做了詳細講解。 枚舉,是一種重要的數據類型,由一組鍵值對組成,通常用來在編程
    的頭像 發表于 09-02 09:43 ?5233次閱讀

    帶你了解go語言中的閉包

    ? 【 導讀】什么是閉包? 什么場景下會用閉包 ? 本文對 go 語言中的閉包做了詳細介紹。 閉包是由函數及其相關引用環境組合而成的實體(即:閉包=函數+引用環境)。 Go中的閉包 閉包是函數式
    的頭像 發表于 11-02 15:27 ?2497次閱讀

    Go并發模型的實現原理

    Go語言是為并發而生的語言,Go語言是為數不多的在語言
    的頭像 發表于 04-15 08:49 ?1426次閱讀

    go語言中怎么使用HTTP代理

    go語言中怎么使用HTTP代理。
    的頭像 發表于 09-01 14:41 ?2466次閱讀
    主站蜘蛛池模板: 天天爽视频| 国内真实实拍伦视频在线观看 | 免费jyzzjyzz在线播放大全 | 手机午夜看片 | 四虎影视永久在线观看 | 能可以直接看的av网址 | 亚洲毛片网 | se97se成人亚洲网站 | 伊人天伊人天天网综合视频 | 亚洲国产七七久久桃花 | 天天做天天爱天天爽综合区 | 狠狠婷婷 | 国产伦精品一区二区三区女 | 亚洲加勒比在线 | 手机看片福利盒子久久青 | 91高清在线成人免费观看 | 美女张开腿露尿口给男人亲 | 99久热只有精品视频免费观看17 | 特黄日韩免费一区二区三区 | 国内黄色一级片 | 伊人精品视频在线 | 一区二区三区四区国产精品 | 国产免费成人在线视频 | 亚洲www在线 | 成人精品一区二区不卡视频 | 亚洲成人看片 | jlzzjlzz欧美大全 | 午夜视频h| 日本写真高清视频免费网站网 | 狠狠色噜噜狠狠狠狠2018 | 999毛片 | 午夜短视频 | 黄黄视频在线观看 | 三级网站在线免费观看 | 国产精品三级a三级三级午夜 | 看黄在线观看 | 奇米影视7777 | 午夜影院官网 | 69日本xxxxxxxxx56| 美女被羞羞产奶视频网站 | 国模大尺度在线 |