我最近開始學習圍棋,我已經在這個問題上花了一段時間了,但我想是時候尋求一些具體的幫助了。我的程序從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)
- 1 回答
- 0 關注
- 191 瀏覽
添加回答
舉報
0/150
提交
取消