zoukankan      html  css  js  c++  java
  • 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)])

     修改第二个会影响结果。

  • 相关阅读:
    js + html 实现视频截图
    检测浏览器版本是否支持webp
    【安装系统】win8装win7遇到的一些坑
    《说文解字》与程序设计
    朝花夕拾——更新两个开源项目
    js发送和接收二进制字节流数据
    字符编码--丛起原到代码
    JavaScript进行WebSocket字节流通讯示例
    JavaScript进行UTF-8编码与解码
    JS字符串与二进制的相互转化
  • 原文地址:https://www.cnblogs.com/9527s/p/13306491.html
Copyright © 2011-2022 走看看