我最近开始学习围棋,我已经在这个问题上花了一段时间了,但我想是时候寻求一些具体的帮助了。我的程序从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 关注
- 203 浏览
添加回答
举报
0/150
提交
取消