在上述程序的第 11 行中, fruitslice 的容量是重置的。以上程序输出为,
length of slice 2 capacity 6 After re-slicing length is 6 and capacity is 6
追加切片元素
正如我们已经知道数组的长度是固定的,它的长度不能增加。 切片是动态的,使用 append 可以将新元素追加到切片上。append 函数的定义是
func append(s[]T,x ... T)[]T
append可以直接在切片尾部追加元素,也可以将一个切片追加到另一个切片尾部。
package main
import (
"fmt"
)
func main() {
str := []string{"a", "b", "c"}
fmt.Println("strs:", str, " length:", len(str), "capacity:", cap(str))
str = append(str, "d")
fmt.Println("strs:", str, " length:", len(str), " capacity:", cap(str))
}
在上述程序中, str 的容量最初是 3。在第 10 行,我们给 str 添加了一个新的元素,并把 append(str, "d") 返回的切片赋值给 str。现在 str 的容量翻了一番,变成了 6。
strs: [a b c] length: 3 capacity: 3 strs: [a b c d] length: 4 capacity: 6
切片类型的零值为 nil 。一个 nil 切片的长度和容量为 0。可以使用 append 函数将值追加到 nil 切片。
package main
import (
"fmt"
)
func main() {
var strs []string //zero value of a slice is nil
if strs == nil {
fmt.Println("slice is nil going to append")
strs = append(strs, "a", "b", "c")
fmt.Println("string contents:",strs)
}
}
在上面的程序 names 是 nil,我们已经添加 3 个字符串给 names 。该程序的输出是
slice is nil going to append string contents: [a b c]
也可以使用 ... 运算符将一个切片添加到另一个切片。
package main
import (
"fmt"
)
func main() {
veggies := []string{"potatoes", "tomatoes", "brinjal"}
fruits := []string{"oranges", "apples"}
food := append(veggies, fruits...)
fmt.Println("food:",food)
}
在上述程序的第 10 行,food 是通过 append(veggies, fruits...) 创建。程序的输出为 food: [potatoes tomatoes brinjal oranges apples] 。
特别需要注意的是如果新切片的长度未超过源切片的容量,则返回源切片,如果追加后的新切片长度超过源切片的容量,则会返回全新的切片。
func main() {
s1 := []int{1,2,3,4,5}
fmt.Printf("s1:%p %d %d %vn",s1,len(s1),cap(s1),s1)
s2 :=append(s1,6)
fmt.Printf("s3:%p %d %d %vn",s2,len(s2),cap(s2),s2)
s3 := s1[0:4]
fmt.Printf("s3:%p %d %d %vn",s3,len(s3),cap(s3),s3)
s4 := append(s3,6)
fmt.Printf("s4:%p %d %d %vn",s4,len(s4),cap(s4),s4)
fmt.Printf("s1:%p %d %d %vn",s1,len(s1),cap(s1),s1)
s5 := append(s4,8)
fmt.Printf("s5:%p %d %d %vn",s5,len(s5),cap(s5),s5)
}
切片的函数传递
切片包含长度、容量和指向数组第零个元素的指针。当切片传递给函数时,即使它通过值传递,指针变量也将引用相同的底层数组。因此,当切片作为参数传递给函数时,函数内所做的更改也会在函数外可见。










