五分钟学会Go这个Append内建函数~

152 阅读3分钟

append

append是golang中的一个内建函数,它的作用是官方的介绍是

The append built-in function appends elements to the end of a slice. If it has sufficient capacity, the destination is resliced to accommodate the new elements. If it does not, a new underlying array will be allocated. Append returns the updated slice. It is therefore necessary to store the result of append, often in the variable holding the slice itself.

append 内置函数将元素追加到切片的末尾。如果它有足够的容量,则重新切片容纳新元素。如果没有,将分配一个新的底层数组,并且 Append 返回更新后的新的切片。因此有必要存储追加的结果,通常会保存原切片中。

定义:

func append(slice []Type, elems ...Type) []Type

用法:

slice = append(slice, elem1, elem2) slice = append(slice, anotherSlice...)

特别地,将字符串附加到字节切片是合法的:

slice = append([]byte("hello "), "world"...)

调用append函数时,append函数会返回一个新的切片接收。如果原切片长度加上新追加的长度没有超过容量则在原有数组上追加元素,新旧切片会指向相同的数组,这时对其中一个切片的修改会同时影响到另一个切片;当原切片长度加上新追加的长度如果超过容量则会新建一个数组,新旧切片会指向不同的数组。 另外还有一个值得注意的点是,切片只会感知len范围内数组内容。

通过一个例子来更好地理解

可以看到虽然ss1和ss2都指向了同一个数组地址,但是ss1的len=0,与ss2的len=1不一致,因为ss1与ss2不是一个切片,只能感知到len范围内的元素,ss1包含0个元素,因此ss1输出的是空,ss2输出了元素1。

切片的内部结构包含地址、大小和容量

ss3和ss4也指向了同一个数组地址,但是与ss1、ss2不同的是,ss3和ss4是有该数组共享部分的,即元素1,而元素2不属于ss3,即使元素1和2都在该数组里面。

  func main() {
    ss1 := make([]string, 0, 10)
    ss2 := append(ss1, "1")
    fmt.Println(fmt.Sprintf("%s 切片指向的数组地址(%p) 切片自身的地址(%p),len(%v),cap(%v),", "ss1", ss1, &ss1, len(ss1), cap(ss1)), ss1)
    fmt.Println(fmt.Sprintf("%s 切片指向的数组地址(%p) 切片自身的地址(%p),len(%v),cap(%v),", "ss2", ss2, &ss2, len(ss2), cap(ss2)), ss2)
  
    ss3 := make([]string, 1, 10)
    ss3[0] = "1"
    ss4 := append(ss3, "2")
    fmt.Println(fmt.Sprintf("%s 数组地址(%p) 切片指向的数组地址(%p) 切片自身的地址(%p),len(%v),cap(%v),", "ss3", &ss3[0], ss3, &ss3, len(ss3), cap(ss3)), ss3)
    fmt.Println(fmt.Sprintf("%s 数组地址(%p) 切片指向的数组地址(%p) 切片自身的地址(%p),len(%v),cap(%v),", "ss4", &ss4[0], ss4, &ss4, len(ss4), cap(ss4)), ss4)
  }
  ss1 切片指向的数组地址(0xc0000b2000) 切片自身的地址(0xc0000a4018),len(0),cap(10), []
  ss2 切片指向的数组地址(0xc0000b2000) 切片自身的地址(0xc0000a4030),len(1),cap(10), [1]
  ss3 数组地址(0xc0000b20a0) 切片指向的数组地址(0xc0000b20a0) 切片自身的地址(0xc0000a40a8),len(1),cap(10), [1]
  ss4 数组地址(0xc0000b20a0) 切片指向的数组地址(0xc0000b20a0) 切片自身的地址(0xc0000a40c0),len(2),cap(10), [1 2]