type student struct {
Name string
Age int
}
func three() int {
m := make(map[string]*student)
stus := []student{
{Name: "zhou", Age: 24},
{Name: "li", Age: 23},
{Name: "wang", Age: 22},
}
for _, stu := range stus {
m[stu.Name] = &stu
}
for k, v := range m {
println(k, "=>", v.Name)
// zhou => wang
// li => wang
// wang => wang
}
}
这里的输出为什么不是?
zhou => zhou
li => li
wang => wang
这里的原因在于使用 for range 遍历的时候,k, v 使用的同一块内存。
为什么?直接查看源码:
func walkRange(nrange *ir.RangeStmt) ir.Node {
...
switch t.Kind() {
case types.TMAP:
// order.stmt allocated the iterator for us.
// we only use a once, so no copy needed.
ha := a
hit := nrange.Prealloc
th := hit.Type()
// depends on layout of iterator struct.
// See cmd/compile/internal/reflectdata/reflect.go:MapIterType
keysym := th.Field(0).Sym // 定义了 key 的地址
elemsym := th.Field(1).Sym // ditto 定义了 value 的地址
fn := typecheck.LookupRuntime("mapiterinit")
fn = typecheck.SubstArgTypes(fn, t.Key(), t.Elem(), th)
init = append(init, mkcallstmt1(fn, reflectdata.TypePtr(t), ha, typecheck.NodAddr(hit)))
nfor.Cond = ir.NewBinaryExpr(base.Pos, ir.ONE, ir.NewSelectorExpr(base.Pos, ir.ODOT, hit, keysym), typecheck.NodNil())
fn = typecheck.LookupRuntime("mapiternext")
fn = typecheck.SubstArgTypes(fn, th)
nfor.Post = mkcallstmt1(fn, typecheck.NodAddr(hit))
key := ir.NewStarExpr(base.Pos, ir.NewSelectorExpr(base.Pos, ir.ODOT, hit, keysym))
if v1 == nil {
body = nil
} else if v2 == nil {
body = []ir.Node{ir.NewAssignStmt(base.Pos, v1, key)}
} else {
elem := ir.NewStarExpr(base.Pos, ir.NewSelectorExpr(base.Pos, ir.ODOT, hit, elemsym))
a := ir.NewAssignListStmt(base.Pos, ir.OAS2, []ir.Node{v1, v2}, []ir.Node{key, elem})
body = []ir.Node{a}
}
...
}
由此可以发现,key 和 value 在进入 range 时,地址被重新指定了。
除了遍历时的地址外,还有一点需要注意,map 遍历的顺序是无序的。源码如下:
func makemap(t *maptype, hint int, h *hmap) *hmap {
mem, overflow := math.MulUintptr(uintptr(hint), t.bucket.size)
if overflow || mem > maxAlloc {
hint = 0
}
// initialize Hmap
if h == nil {
h = new(hmap)
}
h.hash0 = fastrand() // 随机种子
...
}
即 map 在运行时的会使用随机种子,因此,上面程序中得到的 wang
是由随机种子决定的。
网友评论