亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在 goroutine 中難以弄清楚數據競爭

在 goroutine 中難以弄清楚數據競爭

Go
慕妹3146593 2022-08-01 19:10:38
我最近開始學習圍棋,我已經在這個問題上花了一段時間了,但我想是時候尋求一些具體的幫助了。我的程序從API請求分頁數據,因為大約有160頁的數據。這似乎是對goroutines的一個很好的使用,除了我有比賽條件,我似乎不知道為什么。這可能是因為我是該語言的新手,但我的印象是,除非它是指針,否則函數的參數將作為調用它的函數中的數據副本傳遞。根據我認為我知道的,這應該是復制我的數據,這讓我可以自由地在主函數中更改它,但我最終多次請求一些頁面,而其他頁面只請求一次。我的主.gopackage mainimport (    "bufio"    "encoding/json"    "log"    "net/http"    "net/url"    "os"    "strconv"    "sync"    "github.com/joho/godotenv")func main() {    err := godotenv.Load()    if err != nil {        log.Fatalln(err)    }    httpClient := &http.Client{}    baseURL := "https://api.data.gov/ed/collegescorecard/v1/schools.json"    filters := make(map[string]string)    page := 0    filters["school.degrees_awarded.predominant"] = "2,3"    filters["fields"] = "id,school.name,school.city,2018.student.size,2017.student.size,2017.earnings.3_yrs_after_completion.overall_count_over_poverty_line,2016.repayment.3_yr_repayment.overall"    filters["api_key"] = os.Getenv("API_KEY")    outFile, err := os.Create("./out.txt")    if err != nil {        log.Fatalln(err)    }    writer := bufio.NewWriter(outFile)    requestURL := getRequestURL(baseURL, filters)    response := requestData(requestURL, httpClient)    wg := sync.WaitGroup{}    for (page+1)*response.Metadata.ResultsPerPage < response.Metadata.TotalResults {        page++        filters["page"] = strconv.Itoa(page)        wg.Add(1)        go func() {            defer wg.Done()            requestURL := getRequestURL(baseURL, filters)            response := requestData(requestURL, httpClient)            _, err = writer.WriteString(response.TextOutput())            if err != nil {                log.Fatalln(err)            }        }()    }    wg.Wait()}我知道我將遇到的另一個問題是以正確的順序寫入輸出文件,但我相信使用通道告訴每個例程完成寫入的請求可以解決這個問題。如果我在這一點上不正確,我將不勝感激關于如何解決這個問題的任何建議。
查看完整描述

1 回答

?
慕仙森

TA貢獻1827條經驗 獲得超8個贊

goroutines不接收數據的副本。當編譯器檢測到變量“轉義”當前函數時,它會在堆上分配該變量。在這種情況下,就是這樣一個變量。當 goroutine 啟動時,它訪問的映射與主線程相同。由于您在主線程中不斷修改而不鎖定,因此無法保證 goroutine 看到的內容。filtersfiltersfilters


我建議你保持只讀,通過復制中的所有項目在goroutine中創建新地圖,然后在goroutine中添加。您還必須小心傳遞的副本:filtersfilters"page"page


go func(page int) {

   flt:=make(map[string]string)

   for k,v:=range filters {

     flt[k]=v

   }

   flt["page"]=strconv.Itoa(page)

   ...

} (page)


查看完整回答
反對 回復 2022-08-01
  • 1 回答
  • 0 關注
  • 191 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號