英文:
How do I properly use nested for loop to range over rows in golang?
问题
我正在尝试按照以下方式迭代嵌套循环,但是在第一个循环中声明的变量(如varOne,varTwo,varThree
)无法传递到第二个循环中。
事实上,在for rowTwo := range rowsTwo {
这一行之后,没有任何代码能够执行。
请问有人可以指出我做错了什么,或者如何改进吗?
func StudentScore() {
var appendedScores []interface{}
for rowOne := range rowsOne {
varOne := rowOne.FirstName
varTwo := rowOne.LastName
varThree := rowOne.UserName
req, _ := http.NewRequest("GET", fmt.Sprintf("https://example.com/users/%s/score", varThree), nil)
client := &http.Client{}
resp, _ := client.Do(req)
type responseData struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Score float64 `json:"score"`
}
type StudentData struct {
UserName string `json:"username_name"`
Score float64 `json:"score"`
}
var rowsTwo []responseData
respBody, _ := ioutil.ReadAll(resp.Body)
err = json.Unmarshal(respBody, &rowsTwo)
fmt.Println("response: ", rowsTwo)
// var appendedScores []interface{}
studentData := &StudentData{}
for rowTwo := range rowsTwo {
fmt.Println("print vars from first loop: ", varOne, varTwo, varThree)
fmt.Println("api response: ", resp)
studentData.UserName=string(varThree)
studentData.Score=float64(rowTwo.Score)
appendedScores = append(appendedScores, *studentData)
}
}
fmt.Println("student scores: ", appendedScores)
}
我想做的事情基本上是使用第一个循环中的行的值生成新的值,然后在第二个循环中使用这些新值,以便我可以得到最终要打印的值。所以嵌套的两个循环的唯一原因是我需要第一个循环中的值。
我是否遗漏了什么,或者有更好的方法来实现这个目标?
英文:
I am trying to iterate over nested loop as below
but the variables declared in first loop like varOne, varTwo, varThree
do not get to the second loop
Matter of fact nothing works after the line for rowTwo := range rowsTwo {
Can anyone please point me to what am doing wrong or how to
func StudentScore() {
var appendedScores []interface{}
for rowOne := range rowsOne {
varOne := rowOne.FirstName
varTwo := rowOne.LastName
varThree := rowOne.UserName
req, _ := http.NewRequest("GET", fmt.Sprintf("https://example.com/users/%s/score", varThree), nil)
client := &http.Client{}
resp, _ := client.Do(req)
type responseData struct {
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Score float64 `json:"score"`
}
type StudentData struct {
UserName string `json:"username_name"`
Score float64 `json:"score"`
}
var rowsTwo []responseData
respBody, _ := ioutil.ReadAll(resp.Body)
err = json.Unmarshal(respBody, &rowsTwo)
fmt.Println("response: ", rowsTwo)
// var appendedScores []interface{}
studentData := &StudentData{}
for rowTwo := range rowsTwo {
fmt.Println("print vars from first loop: ", varOne, varTwo, varThree)
fmt.Println("api response: ", resp)
studentData.UserName=string(varThree)
studentData.Score=float64(rowTwo.Score)
appendedScores = append(appendedScores, *studentData)
}
}
fmt.Println("student scores: ", appendedScores)
}
Pretty much what am trying to do is use the values from the rows in the first range of rows and use to generate new values to use in the second for loop so i can have a final value to print. So the only reason for the 2 nested for loops is because i need values from first for loop
Is there something am missing or a better way to do this?
答案1
得分: 1
type StudentScore struct {
UserName string `json:"user_name"`
Score float64 `json:"score"`
}
func GetStudentScore() ([]StudentScore, error) {
var scores []StudentScore
for _, row := range rowsOne {
s := StudentScore{UserName: row.UserName}
// 请求分数数据
resp, err := http.Get(fmt.Sprintf("https://example.com/users/%s/score", s.UserName))
if err != nil {
return nil, err
}
defer resp.Body.Close()
// 解析分数数据
var data struct {
Score float64 `json:"score"`
}
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
return nil, err
}
// 设置学生实例的分数字段
s.Score = data.Score
// 添加学生分数
scores = append(scores, s)
}
return scores, nil
}
要并发执行,你可以像下面这样做:
type StudentScore struct {
UserName string `json:"user_name"`
Score float64 `json:"score"`
}
func GetStudentScore() ([]StudentScore, error) {
var wg sync.WaitGroup
var ch = make(chan StudentScore)
for _, row := range rowsOne {
wg.Add(1)
// 对于每一行,在单独的 goroutine 中执行 retrieveStudentScore 函数
go func(row Row) {
if err := retrieveStudentScore(row.UserName, ch); err != nil {
log.Println("获取学生分数失败:", err)
}
wg.Done()
}(row)
}
go func() {
wg.Wait() // 等待所有 retrieveStudentScore 完成
close(ch) // 这会导致下面的 range 循环退出
}()
var scores []StudentScore
for s := range ch {
// 从通道接收到的 StudentScore 添加到切片中
scores = append(scores, s)
}
return scores, nil
}
func retrieveStudentScore(userName string, ch chan StudentScore) error {
// 请求分数数据
resp, err := http.Get(fmt.Sprintf("https://example.com/users/%s/score", userName))
if err != nil {
return err
}
defer resp.Body.Close()
// 解析分数数据
var data struct {
Score float64 `json:"score"`
}
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
return err
}
// 将 StudentScore 发送到通道中
ch <- StudentScore{UserName: userName, Score: data.Score}
return nil
}
英文:
type StudentScore struct {
UserName string `json:"user_name"`
Score float64 `json:"score"`
}
func GetStudentScore() ([]StudentScore, error) {
var scores []StudentScore
for _, row := range rowsOne {
s := StudentScore{UserName: row.UserName}
// request score data
resp, err := http.Get(fmt.Sprintf("https://example.com/users/%s/score", s.UserName))
if err != nil {
return nil, err
}
defer resp.Body.Close()
// unmarshal score data
var data struct {
Score float64 `json:"score"`
}
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
return nil, err
}
// set score field on Student instance
s.Score = data.Score
// append StudentScore
scores = append(scores, s)
}
return scores, nil
}
To do it concurrently you could do something like the following:
type StudentScore struct {
UserName string `json:"user_name"`
Score float64 `json:"score"`
}
func GetStudentScore() ([]StudentScore, error) {
var wg sync.WaitGroup
var ch = make(chan StudentScore)
for _, row := range rowsOne {
wg.Add(1)
// for each row execute the retrieveStudentScore in a separate goroutine
go func() {
if err := retrieveStudentScore(row.UserName, ch); err != nil {
log.Println("failed to retrieve StudentScore:", err)
}
wg.Done()
}()
}
go func() {
wg.Wait() // wait until every retrieveStudentScore is finished
close(ch) // this will cause the range loop below to exit
}()
var scores []StudentScore
for s := range ch {
// append StudentScore received from channel
scores = append(scores, s)
}
return scores, nil
}
func retrieveStudentScore(userName string, ch chan StudentScore) error {
// request score data
resp, err := http.Get(fmt.Sprintf("https://example.com/users/%s/score", userName))
if err != nil {
return err
}
defer resp.Body.Close()
// unmarshal score data
var data struct {
Score float64 `json:"score"`
}
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
return err
}
// send StudentScore to channel
ch <- StudentScore{UserName: userName, Score: data.Score}
return nil
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论