slice

本文详细探讨了Go语言中切片的工作原理,包括如何在函数内部修改底层数组,如何比较切片(特别是字符串切片),以及容量扩张和append操作对内存的影响。同时,通过将切片比作栈,解释了入栈和出栈的概念,以及如何删除切片中间元素。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最重要的一张图

endlessSummer :=summer[:5]//这是这张图真正厉害的地方

为什么向函数传递slice允许在函数内部修改底层数组的元素?

因为slice值包含指向第一个sllice元素的指针,传入的slice允许在函数内部修改底层数组的元素。

复制的slice只是对底层的数组创建了一个新的slice别名

// reverse reverses a slice of ints in place.
func reverse(s []int) {
    for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
        s[i], s[j] = s[j], s[i]
    }
}

这个函数是对传入的切片做真实的翻转

slice并没有指明序列的长度,从声明就可以看得出来

s := []int{0,1,12,34,3,4}

slice不能比较,数组可以比较:数组的类型和数值都相同的时候才可以相等

除了byte类型的slice可以进行比较:bytes.Equal

对其他类型只能进行逐一比较

func equal(x,y []string) bool{
  if len(x)!= len(y){
    return false
  }
  for i:=range x{
    if x[i]!=y[i]{
    return false
    }
  }
  return true
}

一个零值的slice等于nil,一个nil值的slice并没有底层数组

var s []int
s = nil
s = []int(nil)

但是一个slice为空,不等于它为nil

我们使用len(s) == 0来判断数组是否为空

一个nil值的slice的行为和其他任意0长度的slice是一样的

reverse(nil)是正确的

看下面这个make语法

make([]T,len)
make([]T,len,cap)

这里的话如果我们没有指出cap,cap = len,在第二个语句中,slice只引用了底层数组前len个元素

append 函数

最重要的一个代码就是容量的扩张

func main() {
    var x, y []int
    for i := 0; i < 10; i++ {
        y = appendInt(x, i)
        fmt.Printf("%d cap=%d\t%v\n", i, cap(y), y)
        x = y
    }
}

每一次容量的变化都会导致重新分配内存和copy操作:

0  cap=1    [0]
1  cap=2    [0 1]
2  cap=4    [0 1 2]
3  cap=4    [0 1 2 3]
4  cap=8    [0 1 2 3 4]
5  cap=8    [0 1 2 3 4 5]
6  cap=8    [0 1 2 3 4 5 6]
7  cap=8    [0 1 2 3 4 5 6 7]
8  cap=16   [0 1 2 3 4 5 6 7 8]
9  cap=16   [0 1 2 3 4 5 6 7 8 9]

slice模拟stack ,了解一下

入栈:

stack = append(stack,v)

slice顶部位置对应slice的最后一个位置

top := stack[:len(stack)-1]

出栈:

stack = stack[:len(stack)-1]

删除slice中间元素

func remove(slice []int,i int) []int{
  copy(slice[i:],slice[i+1:])
  return slice[:len(slice)-1]
}
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值