天天看点

Golang 切片append

强烈建议:go的50度灰

在用Golang切片的时候,

case1.

比如声明:

nums := make([]int, 0)

这里给nums append的时候,需要使用 nums = append(nums, 1);

case2.

data := make([]int, 10)
	for  i := 0; i < 10; i++ {
		data = append(data, i)
	}
	fmt.Printf("len: %d, v:%+v", len(data), data)

输出:
len: 20, v:[0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9]
           

所以, append操作,是在原有的长度尾巴append!!!!!! 而不是从0开始!!

此外,在一个nil的slice中添加元素是没问题的,但对一个map做同样的事将会生成一个运行时的panic。

正确:

package main
func main() {  
    var s []int
    s = append(s,1) // 正确
}
           

错误:

package main
func main() {  
    var m map[string]int
    m["one"] = 1 //error
}
           

多维slice

table := make([][]int, 2)
    
	table[0] = []int{1,2,3}//正确
	//table[0][5] = 8 // error 索引溢出
    //table[1][0]=7 panic: runtime error: index out of range [0] with length 0
    table[1] = append(table[1], 4,5,6)//正确
   //table[2] = []int{7,8,9} panic: runtime error: index out of range [2] with length 2
    table = append(table, []int{7,8,9}) // 正确
           

综上,slice可以直接append,但是不能直接用索引取不存在的index(性质相同于Java的List: 可以add,但是不能用不存在的index取get() )

nil 切片和空切片

nile切片和空切片

注意,不管是哪个切片,用 append都是正常使用的!! 不会Panic!!!

旧切片

当从一个已存在的 slice 创建新 slice 时(尤其是使用[begin:end] 这种截取slice片段的方法),二者的数据指向相同的底层数组。,那需要注意 “旧”(stale) slice 问题。

某些情况下,向一个 slice 中追加元素而它指向的底层数组容量不足时,将会重新分配一个新数组来存储数据。而其他 slice 还指向原来的旧底层数组。

func main() {
    s1 := []int{1, 2, 3}
    fmt.Println(len(s1), cap(s1), s1)    // 3 3 [1 2 3 ]

    s2 := s1[1:]
    fmt.Println(len(s2), cap(s2), s2)    // 2 2 [2 3]

    for i := range s2 {
        s2[i] += 20
    }
    // 此时的 s1 与 s2 是指向同一个底层数组的
    fmt.Println(s1)        // [1 22 23]
    fmt.Println(s2)        // [22 23]

    s2 = append(s2, 4)// 向容量为 2 的 s2 中再追加元素,重新存储此时将分配新数组来存

    for i := range s2 {
        s2[i] += 10
    }
    fmt.Println(s1)        // [1 22 23]    // 此时的 s1 不再更新,为旧数据
    fmt.Println(s2)        // [32 33 14]
}