Go Slice 使用中的小陷阱

go中的切片有两个特性:

  • 底层的数据结构是数组
type slice struct {
  array unsafe.Pointer
  len   int
  cap   int
}

包括从切片和数组派生出来的切片都是公用一个底层数组的

  • 当往切片append的元素超过容量时,即len(s) < cap(s)时,底层的数组会重新分配一个容量更大的数组
  • make构造出来的切片,已经预先填充了len个零值元素了。

总而言之,对切片的更改都会影响到底层的数组结构,因此需要慎重。
动手做个实验:

package main

import (
	"fmt"
)

func double(s []int, count int) {
  fmt.Println("函数调用内切片的长度为", len(s), " 容量为", cap(s))
  for i:=0; i < count; i++ {
    s = append(s, 100) 
  }

  for i, v := range s {
    s[i] = v * 2
  }
}

func main() {
  s := make([]int, 5, 10)
  // 下面的赋值会改变s的底层数组,导致上面指定的容量10失效
  // s = []int{
  //   1, 2, 3, 4, 5,
  // }
  for i:=0; i < 5; i++ {
    s[i] = i + 1
  }

  fmt.Println("主函数内切片的长度为", len(s), " 容量为", cap(s))
  fmt.Println(s)
  double(s, 1)
  fmt.Println(s)
  // 添加超过切片容量的元素后,double函数内切片底层的数组重新分配了,和主函数外的切片的底层数组不是同一个了,因此对其修改不会影响到主函数切片的数值
  double(s, 10)
  fmt.Println(s)
}
posted @   yihailin  阅读(228)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
点击右上角即可分享
微信分享提示