Go 语言中数组和切片都属于集合类的类型,它们的值也都可以用来存储某一种类型的值(或者说元素)。数组类型的值的长度是固定的,而切片类型的值(以下简称切片)是可变长的。数组的长度在声明它的时候就必须给定,并且之后不会再改变。而切片的类型字面量中只有元素的类型,而没有长度。切片的长度可以自动地随着其中元素数量的增长而增长,但不会随着元素数量的减少而减小。
functcMake(n *ir.CallExpr) ir.Node { // --- 省略代码 --- case types.TSLICE: if i >= len(args) { base.Errorf("missing len argument to make(%v)", t) n.SetType(nil) return n } l = args[i] i++ l = Expr(l) var r ir.Node if i < len(args) { r = args[i] i++ r = Expr(r) }
if l.Type() == nil || (r != nil && r.Type() == nil) { n.SetType(nil) return n } if !checkmake(t, "len", &l) || r != nil && !checkmake(t, "cap", &r) { n.SetType(nil) return n } if ir.IsConst(l, constant.Int) && r != nil && ir.IsConst(r, constant.Int) && constant.Compare(l.Val(), token.GTR, r.Val()) { base.Errorf("len larger than cap in make(%v)", t) n.SetType(nil) return n } nn = ir.NewMakeExpr(n.Pos(), ir.OMAKESLICE, l, r) // --- 省略代码 --- } // --- 省略代码 --- nn.SetType(t) return nn }
package main import"fmt" funcmain() { s := make([]int, 0) oldCap := cap(s) for i := 0; i < 2048; i++ { s = append(s, i) newCap := cap(s) if newCap != oldCap { fmt.Printf("[%d -> %4d] cap = %-4d | after append %-4d cap = %-4d\n", 0, i-1, oldCap, i, newCap) oldCap = newCap } } }
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
[0 -> -1] cap = 0 | after append 0 cap = 1 [0 -> 0] cap = 1 | after append 1 cap = 2 [0 -> 1] cap = 2 | after append 2 cap = 4 [0 -> 3] cap = 4 | after append 4 cap = 8 [0 -> 7] cap = 8 | after append 8 cap = 16 [0 -> 15] cap = 16 | after append 16 cap = 32 [0 -> 31] cap = 32 | after append 32 cap = 64 [0 -> 63] cap = 64 | after append 64 cap = 128 [0 -> 127] cap = 128 | after append 128 cap = 256 [0 -> 255] cap = 256 | after append 256 cap = 512 [0 -> 511] cap = 512 | after append 512 cap = 1024 [0 -> 1023] cap = 1024 | after append 1024 cap = 1280 [0 -> 1279] cap = 1280 | after append 1280 cap = 1696 [0 -> 1695] cap = 1696 | after append 1696 cap = 2304