Golang可以通过:=声明的同时为变量赋值,还有变量的作用域也需要注意。for循环体中声明的变量作用域从for循环开始到花括号结束。 给出一组学生的各科成绩,可能有重复的,学生的姓名唯一,按照姓名对分数求和。
package main
import "fmt"
type student struct {
Score int
Name string
}
func printMap(m map[string]*student) {
for k, v := range m {
fmt.Println(k, v)
}
}
func main() {
s := make([]student, 0)
s = append(s, student{1, "s1"})
s = append(s, student{1, "s2"})
s = append(s, student{2, "s1"})
s = append(s, student{1, "s3"})
m := make(map[string]*student)
for idx, v := range s {
_, ok := m[v.Name]
if !ok {
m[v.Name] = &v
} else {
m[v.Name].Score += v.Score
}
fmt.Println(idx)
printMap(m)
}
printMap(m)
}
上面代码最终的输出:
s1 &{1 s3}
s2 &{1 s3}
s3 &{1 s3}
因为v的作用域在整个for循环,每次赋值的是v的地址,固定不变,所有value都被赋值为同一个值了。改成如下代码:
package main
import "fmt"
type student struct {
Score int
Name string
}
func printMap(m map[string]*student) {
for k, v := range m {
fmt.Println(k, v)
}
}
func main() {
s := make([]student, 0)
s = append(s, student{1, "s1"})
s = append(s, student{1, "s2"})
s = append(s, student{2, "s1"})
s = append(s, student{1, "s3"})
m := make(map[string]*student)
for idx, v := range s {
_, ok := m[v.Name]
if !ok {
m[v.Name] = &s[idx]
} else {
m[v.Name].Score += v.Score
}
}
printMap(m)
}
输出:
s1 &{3 s1}
s2 &{1 s2}
s3 &{1 s3}