Go基础Slice教程详解

2019-11-10 11:34:28于海丽

在上述程序的第 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)
}

切片的函数传递

切片包含长度、容量和指向数组第零个元素的指针。当切片传递给函数时,即使它通过值传递,指针变量也将引用相同的底层数组。因此,当切片作为参数传递给函数时,函数内所做的更改也会在函数外可见。