golang学习笔记——基础03

本文详细介绍了Go语言中的切片概念,包括切片与数组的区别、创建方式、长度与容量、以及切片扩容的工作原理。重点讲解了如何初始化切片和避免因频繁扩容影响性能的方法。
摘要由CSDN通过智能技术生成

切片

需要说明,slice 并不是数组或数组指针。它通过内部指针和相关属性引用数组片段,以实现变长方案。

    1. 切片:切片是数组的一个引用,因此切片是引用类型。但自身是结构体,值拷贝传递。
    2. 切片的长度可以改变,因此,切片是一个可变的数组。
    3. 切片遍历方式和数组一样,可以用len()求长度。表示可用元素数量,读写操作不能超过该限制。 
    4. cap可以求出slice最大扩张容量,不能超出数组限制。0 <= len(slice) <= len(array),其中array是slice引用的数组。
    5. 切片的定义:var 变量名 []类型,比如 var str []string  var arr []int。
    6. 如果 slice == nil,那么 len、cap 结果都等于 0。

创建切片的各种方式

package main

import "fmt"

func main() {
   //1.声明切片
   var s1 []int
   if s1 == nil {
      fmt.Println("是空")
   } else {
      fmt.Println("不是空")
   }
   
   // 2.:=
   s2 := []int{}
   
   // 3.make()
   var s3 []int = make([]int, 0) \\make([]type, len)
   fmt.Println(s1, s2, s3)
   
   // 4.初始化赋值
   var s4 []int = make([]int, 0, 0) \\make([]int,len,cap) 
   fmt.Println(s4)
   s5 := []int{1, 2, 3}
   fmt.Println(s5)
   
   // 5.从数组切片
   arr := [5]int{1, 2, 3, 4, 5}
   var s6 []int
   
   // 前包后不包
   s6 = arr[1:4]
   fmt.Println(s6)
}

切片初始化

全局:
var arr = [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
var slice0 []int = arr[start:end] 
var slice1 []int = arr[:end]        
var slice2 []int = arr[start:]        
var slice3 []int = arr[:] 
var slice4 = arr[:len(arr)-1]      //去掉切片的最后一个元素
局部:
arr2 := [...]int{9, 8, 7, 6, 5, 4, 3, 2, 1, 0} //注意,这个是数组
slice5 := arr[start:end]
slice6 := arr[:end]        
slice7 := arr[start:]     
slice8 := arr[:]  
slice9 := arr[:len(arr)-1] //去掉切片的最后一个元素

数组与切片有时比较难以分辨,可以通过定义与规则来区分

  1. 数组,是同一种数据类型的固定长度的序列。
  2. 切片,是一个拥有相同类型元素的可变长度的序列,它是基于数组类型做的一层封装。它非常灵活,支持自动扩容。切片是一种引用类型,它有三个属性:指针,长度和容量。
  3. 数组长度必须是常量。如果数组长度不确定,可以使用 ... 代替数组的长度,编译器会根据元素个数自行推断数组的长度。如data := [...]int{0, 1, 2, 3, 4}
  4. 语句有make的是切片,有中括号有冒号的是切片,如[:]
  5. 下面这样不确定长度的是切片
    // [] 中括号里面是空的
    s2 := []int{}
    
    // [] 中括号里面是空的
    data := [][]int{
        []int{1, 2, 3},
        []int{100, 200},
        []int{11, 22, 33, 44},
    }
    

go 切片扩容

当切片的长度超过其容量时,切片会自动扩容。这通常发生在使用 append 函数向切片中添加元素时。

扩容时,Go 运行时会分配一个新的底层数组,并将原始切片中的元素复制到新数组中。然后,原始切片将指向新数组,并更新其长度和容量。

需要注意的是,由于扩容会分配新数组并复制元素,因此可能会影响性能。如果你知道要添加多少元素,可以使用 make 函数预先分配足够大的切片来避免频繁扩容。

一、go1.18 之前:

  1. 如果期望容量大于当前容量的两倍就会使用期望容量;
  2. 如果当前切片的长度小于 1024 就会将容量翻倍;
  3. 如果当前切片的长度大于 1024 就会每次增加 25% 的容量,直到新容量大于期望容量;

二、go1.18 之后:

  1. 如果期望容量大于当前容量的两倍就会使用期望容量;
  2. 如果当前切片的长度小于阈值(默认 256)就会将容量翻倍;
  3. 如果当前切片的长度大于等于阈值(默认 256),就会每次增加 25% 的容量,基准是 newcap + 3*threshold,直到新容量大于期望容量;
oldcap扩容系数
2562.0
5121.63
10241.44
20481.35
40961.30

参考

Go 1.18 Release Notes
Go 语言切片是如何扩容的?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值