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

golang并發(fā)執(zhí)行的幾種方式小結(jié)

 更新時間:2023年08月23日 11:07:03   作者:阿十~  
本文主要介紹了golang并發(fā)執(zhí)行的幾種方式小結(jié),主要包括了Channel,WaitGroup ,Context,使用這三種機(jī)制中的一種或者多種可以達(dá)到并發(fā)控制很好的效果,具有一定的參考價值,感興趣的可以了解一下

背景

主要記錄一下工作中和各個文檔里關(guān)于golang并發(fā)開發(fā)的實踐。golang并發(fā)主要用到了

Channel: 使用channel控制子協(xié)程,WaitGroup : 使用信號量機(jī)制控制子協(xié)程,Context: 使用上下文控制子協(xié)程。使用這三種機(jī)制中的一種或者多種可以達(dá)到并發(fā)控制很好的效果。關(guān)于這三個知識點,http://www.dbjr.com.cn/jiaoben/296040z3m.htm介紹的比較詳細(xì)了,這里只介紹幾個場景用法。

實踐

waitGroup并發(fā)執(zhí)行不同任務(wù)

這種寫法適合并發(fā)處理少量case,并且funcA和funcB的作用是不同任務(wù)的時候。

? ? wg := sync.WaitGroup{}
? ? var result1 interface{}
    var result2 interface{}
? ? wg.Add(2)
    go func() {
        defer func() {
            wg.Done()
        }()
        result1 = funcA()
    }()
? ? go func() {
        defer func() {
            wg.Done()
        }()
        result1 = funcB()
    }()  
    wg.wait() 

waitGroup并發(fā)執(zhí)行相同任務(wù)

假設(shè)有一批url,需要并發(fā)去抓取,這個時候可能只是請求的地址不同,任務(wù)的函數(shù)是一致的。這時候可以使用for循環(huán)的方式去批量執(zhí)行。使用該方法時候,需要使用線程安全的結(jié)構(gòu)去做數(shù)據(jù)同步。此外下文的寫法最大的弊端是沒法做并發(fā)度控制,如果請求過多,容易把下游打滿,以及啟過多協(xié)程,浪費資源,只適合小數(shù)據(jù)集,

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "strings"
    "sync"
)
func main() {
    idList := []string{"x", "xx"}
    wg := sync.WaitGroup{}
    dataMap := sync.Map{} //  sync.Map是線程安全的,如果使用 map去存儲返回結(jié)果會報錯,
                          //  接受返回結(jié)果也可以是channel,channel也是線程安全的
    for _, id := range idList {
        wg.Add(1)
        go func(id string) {
            defer func() {
                wg.Done()
            }()
            data := PostData(id)
            dataMap.Store(id, data)
        }(id)
    }
    wg.Wait()
    for _, id := range idList {
        fmt.Println(dataMap.Load(id))
    }
}
func PostData(id string) string {
    url := "http:xx"
    method := "POST"
    payload := strings.NewReader(fmt.Sprintf(`{"id":"%s"}`, id))
    client := &http.Client{}
    req, err := http.NewRequest(method, url, payload)
    if err != nil {
        fmt.Println(err)
        return ""
    }
    req.Header.Add("Content-Type", "application/json")
    res, err := client.Do(req)
    if err != nil {
        fmt.Println(err)
        return ""
    }
    defer res.Body.Close()
    body, err := ioutil.ReadAll(res.Body)
    if err != nil {
        fmt.Println(err)
        return ""
    }
    return string(body)
}

加入channnel,控制并發(fā)度

package main
import (
    "fmt"
    "net/http"
    "sync"
)
func main() {
    urls := []string{"http://a.com", "http://b.com", "http://c.com"}
    // 控制并發(fā)度為2
    concurrency := 2
    sem := make(chan struct{}, concurrency)
    var wg sync.WaitGroup
    for _, url := range urls {
        wg.Add(1)
        go func(url string) {
            sem <- struct{}{} // 獲取信號量
            defer func() {
                <-sem // 釋放信號量
                wg.Done()
            }()
            resp, err := http.Get(url)
            if err != nil {
                fmt.Printf("Error fetching %s: %v\n", url, err)
                return
            }
            defer resp.Body.Close()
            fmt.Printf("Fetched %s with status code %d\n", url, resp.StatusCode)
        }(url)
    }
    wg.Wait()
    fmt.Println("All URLs fetched")
}

使用channel進(jìn)行并發(fā)編程

接下來,我們使用一個for循環(huán)來遍歷URL切片,并為每個URL啟動一個goroutine。在每個goroutine中,我們首先從并發(fā)度通道中獲取一個信號,表示可以開始請求。然后,我們發(fā)送一個http GET請求,并將響應(yīng)結(jié)果發(fā)送到結(jié)果通道中。最后,我們釋放一個信號,表示請求已完成。

在主函數(shù)中,我們使用另一個for循環(huán)從結(jié)果通道中讀取所有響應(yīng)結(jié)果,并將它們打印到控制臺上。

需要注意的是,我們在并發(fā)度通道中使用了一個空結(jié)構(gòu)體{},因為我們只需要通道來控制并發(fā)度,而不需要在通道中傳遞任何數(shù)據(jù)。此外,我們還使用了通道的阻塞特性來控制并發(fā)度,因為當(dāng)通道已滿時,任何試圖向通道中發(fā)送數(shù)據(jù)的操作都會被阻塞,直到有空間可用為止。

package main
import (
    "fmt"
    "net/http"
)
func main() {
    urls := []string{"http://www.google.com", "http://www.facebook.com", "http://www.apple.com"}
    // 創(chuàng)建一個通道來控制并發(fā)度為2
    concurrency := make(chan struct{}, 2)
    // 創(chuàng)建一個通道來接收響應(yīng)結(jié)果
    results := make(chan string, len(urls))
    for _, url := range urls {
        // 啟動一個goroutine來請求url
        go func(url string) {
            // 從通道中獲取一個信號,表示可以開始請求
            concurrency <- struct{}{}
            // 發(fā)送http GET請求
            resp, err := http.Get(url)
            if err != nil {
                results <- fmt.Sprintf("%s -> error: %s", url, err)
            } else {
                results <- fmt.Sprintf("%s -> status: %s", url, resp.Status)
                resp.Body.Close()
            }
            // 釋放一個信號,表示請求已完成
            <-concurrency
        }(url)
    }
    // 從結(jié)果通道中讀取所有響應(yīng)結(jié)果
    for i := 0; i < len(urls); i++ {
        fmt.Println(<-results)
    }
}

使用context,進(jìn)行并發(fā)控制

這種機(jī)制下生成的goruntine是樹形結(jié)構(gòu)的,有依賴關(guān)系。

func getData(ctx context.Context, result chan string, id string) {
    for {
        select {
        case <-ctx.Done():
            fmt.Println("running get Data")
            return
        default:
            resultData := PostData(id)
            result <- resultData
        }
    }
}
func main() {
    idList := []string{"xx", "xxx"}
    ctx := context.Background()
    var result = make(chan string, 2)
    go getData(ctx, result, idList[0])
    go getData(ctx, result, idList[1])
    fmt.Println(<-result)
    fmt.Println(<-result)
}
func PostData(id string) string {
    url := "http://xxx"
    method := "POST"
    payload := strings.NewReader(fmt.Sprintf(`{"id":"%s"}`, id))
    client := &http.Client{}
    req, err := http.NewRequest(method, url, payload)
    if err != nil {
        fmt.Println(err)
        return ""
    }
    req.Header.Add("Content-Type", "application/json")
    res, err := client.Do(req)
    if err != nil {
        fmt.Println(err)
        return ""
    }
    defer res.Body.Close()
    body, err := ioutil.ReadAll(res.Body)
    if err != nil {
        fmt.Println(err)
        return ""
    }
    return string(body)
}

到此這篇關(guān)于golang并發(fā)執(zhí)行的幾種方式小結(jié)的文章就介紹到這了,更多相關(guān)golang并發(fā)執(zhí)行內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解golang中發(fā)送http請求的幾種常見情況

    詳解golang中發(fā)送http請求的幾種常見情況

    這篇文章主要介紹了詳解golang中發(fā)送http請求的幾種常見情況,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • Go語言執(zhí)行cmd命令庫的方法實現(xiàn)

    Go語言執(zhí)行cmd命令庫的方法實現(xiàn)

    go語言用來執(zhí)行一個系統(tǒng)的命令相對python來說還是有點復(fù)雜的,執(zhí)行命令是一個非常常見的需求,本文主要介紹了Go語言執(zhí)行cmd命令庫的方法實現(xiàn),感興趣的可以了解一下
    2023-09-09
  • GOLANG使用Context管理關(guān)聯(lián)goroutine的方法

    GOLANG使用Context管理關(guān)聯(lián)goroutine的方法

    這篇文章主要介紹了GOLANG使用Context管理關(guān)聯(lián)goroutine的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-01-01
  • go使用Viper管理配置文件的方法步驟

    go使用Viper管理配置文件的方法步驟

    在項目開發(fā)中,需要把一些配置配置提取出來,方便配置和管理,可以使用Viper工具,Viper 是 Go 應(yīng)用程序的完整配置解決方案,也支持從環(huán)境變量中讀取,本文給大家介紹了go使用Viper管理配置文件的方法步驟,需要的朋友可以參考下
    2024-07-07
  • Go語法糖之‘...’ 的使用實例詳解

    Go語法糖之‘...’ 的使用實例詳解

    語法糖(Syntactic sugar),也譯為糖衣語法,指計算機(jī)語言中添加的某種語法,這種語法對語言的功能并沒有影響,但是更方便程序員使用。這篇文章主要給大家介紹Go語法糖之‘...’ 的使用,感興趣的朋友一起看看吧
    2018-10-10
  • Golang?基于flag庫實現(xiàn)一個簡單命令行工具

    Golang?基于flag庫實現(xiàn)一個簡單命令行工具

    這篇文章主要介紹了Golang基于flag庫實現(xiàn)一個簡單命令行工具,Golang標(biāo)準(zhǔn)庫中的flag庫提供了解析命令行選項的能力,我們可以基于此來開發(fā)命令行工具,下文詳細(xì)介紹。需要的小伙伴可以參考一下
    2022-08-08
  • go語言beego框架分頁器操作及接口頻率限制示例

    go語言beego框架分頁器操作及接口頻率限制示例

    這篇文章主要為大家介紹了go語言beego框架分頁器操作使用示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04
  • 通過Golang編寫一個AES加密解密工具

    通過Golang編寫一個AES加密解密工具

    這篇文章主要為大家詳細(xì)介紹了如何利用Golang制作一個AES加密解密工具,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-05-05
  • GoLang BoltDB數(shù)據(jù)庫詳解

    GoLang BoltDB數(shù)據(jù)庫詳解

    這篇文章主要介紹了GoLang BoltDB數(shù)據(jù)庫,boltdb是使用Go語言編寫的開源的鍵值對數(shù)據(jù)庫,boltdb存儲數(shù)據(jù)時 key和value都要求是字節(jié)數(shù)據(jù),此處需要使用到 序列化和反序列化
    2023-02-02
  • pytorch中的transforms.ToTensor和transforms.Normalize的實現(xiàn)

    pytorch中的transforms.ToTensor和transforms.Normalize的實現(xiàn)

    本文主要介紹了pytorch中的transforms.ToTensor和transforms.Normalize的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04

最新評論