我们已经知道数组的长度是固定的,不能增加。切片长度是动态的,可以使用append
函数将新元素添加到片中。append
函数的定义是func append(s []T, x...T) []T
。
函数定义中的x...T
,表示可变参数,参数类型为T
,传入的参数数量可变,这种函数称为可变参数函数。
不过有一个问题可能困扰着你。如果切片的底层是数组,数组本身的长度是固定的,那么切片长度为什么可以是动态的呢?
当新元素被添加到切片中时,就会创建一个新的数组。将现有数组的元素复制到这个新数组中,并返回这个新数组的一个新切片引用。
现在新切片的容量变大了(具体增加多少,由go决定)。
来看一个例子:
package main
import (
"fmt"
)
func main() {
cars := []string{"Ferrari", "Honda", "Ford"}
fmt.Println("cars:", cars, "has old length", len(cars), "and capacity", cap(cars)) //capacity of cars is 3
cars = append(cars, "Toyota")
fmt.Println("cars:", cars, "has new length", len(cars), "and capacity", cap(cars)) //capacity of cars is doubled to 6
}
在上述方案中,切片cars
的初始容量为3,给这个切片增加一个新元素,将append(cars,"Toyota")
返回的切片,重新分配给cars
。现在cars
的容量增加了一倍,变成了6辆。以上程序的输出为
cars: [Ferrari Honda Ford] has old length 3 and capacity 3
cars: [Ferrari Honda Ford Toyota] has new length 4 and capacity 6
切片类型的零值为nil
。值为nil
的切片,其长度和容量为0。可以使用append
函数将值追加到nil
切片。
package main
import (
"fmt"
)
func main() {
var names []string //切片的零值是nil
if names == nil {
fmt.Println("slice is nil going to append")
names = append(names, "John", "Sebastian", "Vinay")
fmt.Println("names contents:",names)
}
}
在上面的程序中,名称是nil
,我们在名称后面附加了3个字符串。程序的输出是
slice is nil going to append
names contents: [John Sebastian Vinay]
也可以使用...
符号将一个切片附加到另一个切片。关于此...
操作符后续变参函数部分会有更多介绍。
package main
import (
"fmt"
)
func main() {
veggies := []string{"potatoes","tomatoes","brinjal"}
fruits := []string{"oranges","apples"}
food := append(veggies, fruits...)
fmt.Println("food:",food)
}
输出: food: [potatoes tomatoes brinjal oranges apples]