go 切片对数组的修改,切片的扩容

go中数组是值拷贝,

切片是对上层数组的表示,应该是使用的是数组地址,修改时是直接对原来的数组进行修改

片作为函数参数依旧如此

slice或者array作为函数参数传递的时候,本质是传值而不是传引用。传值的过程复制一个新的切片,这个切片也指向原始变量的底层数组。

 

 

var array [5]int=[5]int{1,2,3,4,5}//可以简化为array:=[5]int{1,2,3,4,5} 初学所以没有简化
	var slice[]int =array[1:3]

	fmt.Println(array)
	for i:=range slice{
		slice[i]+=100
	}
	fmt.Println(array)

	fmt.Println(slice)

  输出

 

 

 说明切片是对数组的引用,更改切片时原数组会发生变化。

因为切片保留对数组的引用,切片在,数组内存不能回收,所以数组大而使用切片为其中一小部分时应该使用切片的拷贝方式。

 

var array [7]int=[7]int{1,2,3,4,5,6,7}
	var slice[]int =array[:3]
	sliceneed:=make([]int,len(slice))
	copy(sliceneed,slice)
	fmt.Println(sliceneed)

  结果

 

 

 

追加一个一个切片到另一个后面可以用append方式带...

var array [5]int=[5]int{1,2,3,4,5}//可以简化为array:=[5]int{1,2,3,4,5} 初学所以没有简化
	var slice[]int =array[1:3]
	fruits := []int{6,7}
	slice =append(slice,fruits...)

  

 

9.24增加切片扩容机制

部分源码

// src/runtime/slice.go
func growslice(et *_type, old slice, cap int) slice {
// ...省略部分
    newcap := old.cap
    doublecap := newcap + newcap
    if cap > doublecap {//大于两倍使用多的容量
        newcap = cap
    } else {
        if old.len < 1024 {//小于1024 使用两倍
            newcap = doublecap
        } else {//否则依次扩大25%,直到复合容量
            // Check 0 < newcap to detect overflow
            // and prevent an infinite loop.
            for 0 < newcap && newcap < cap {
                newcap += newcap / 4
            }
            // Set newcap to the requested cap when
            // the newcap calculation overflowed.
            if newcap <= 0 {
                newcap = cap
            }
        }
    }
// ...省略部分
}

  

  • 当需要的容量超过原切片容量的两倍时,会使用需要的容量作为新容量。
  • 当原切片长度小于1024时,新切片的容量会直接翻倍。而当原切片的容量大于等于1024时,会反复地增加25%,直到新容量超过所需要的容量。
  为了避免因为切片是否发生扩容的问题导致bug,最好的处理办法还是在必要时使用 copy 来复制数据,保证得到一个新的切片,
  避免后续操作带来预料之外的副作用。

参考链接:https://www.jianshu.com/p/54be5b08a21c

 
 
预测输出
         var x =[]int{1,2,3}
	var y = x[:2]

	y = append(y,50)
	y = append(y,60)
	
	fmt.Println(x)
	y[0] = 20
	fmt.Println(y)

 

 

 结果,y初始和x引用相同底层数组,切容量未超出,所以第一个append正常修改,

 第二个append时超出容量,扩容使用新的底层数组,之后再修改y是更改自己的数据。

 
 
 
 
今天写leetcode遇到个奇怪的问题。
一个切片append另外一个,是非拷贝方式的,修改第二个切片值会影响结果
test:=[]int{1,2,3}
    two:=[]int{4,5,6}
    two[0] = 9

    test = append(test,two...)
    fmt.Println(test[:len(test)])

 

 修改第二个会影响结果。

 

posted @ 2020-07-15 16:51  海拉尔  阅读(1805)  评论(0编辑  收藏  举报