golang中slice切片使用的误区

本文探讨了Go语言中切片初始化的常见误区,解释了为何预先分配长度的切片仍可能包含默认零值,并提供了正确的使用切片避免扩容的方法。通过示例代码,作者展示了如何通过下标指定或使用两种不同初始化方式来正确填充切片,以防止不必要的扩容和错误的元素值。
摘要由CSDN通过智能技术生成

一、前言

      最近在项目代码中,发现了一种写法,如下所示:

//期望是能把id顺序写到切片,把切片占满,元素数为10个
Ids1 := make([]int64, 10)
for _, v := range xxxx {
   Ids1 = append(Ids1, v.ids1)
}

      看起来还可以,提前给切片分配长度,防止append频繁扩容。然而在实际使用中才发现,以上结果打印如下:

Ids1:([0 0 0 0 0 0 0 0 0 0 393 394 395 396 397 398 399 400 401 402])

      是不是跟想象中不一样,这特么的不是说好的分配长度,使用已有长度,怎么打印出来的是0,而且切片依然发生了扩容。

二、切片分配长度的正确用法

1、切片的初始化

      博主百思不得其解,于是去百度切片的用法,发现一般初始化切片如下:

make([]T, len)   //省略cap,len=cap
make([]T, len, cap) // 等价于 make([]T, cap)[:len]

使用make初始化,由于未赋值系统默认将元素值置为0,即:

数值类型数组:   默认值为0
字符串数组:     默认值为""
bool数组:      默认值为false

那么我们打印出来的0值,是否就是被make初始化零值的原因呢?

2、打印切片长度和容量

	Ids1 := make([]int64, 10)
	fmt.Println("Ids1切片长度:", len(Ids1))
	fmt.Println("Ids1切片容量:", cap(Ids1))
	fmt.Println("Ids1切片内容:", Ids1)
	Ids2 := make([]int64, 0, 10)
	fmt.Println("Ids2切片长度:", len(Ids2))
	fmt.Println("Ids2切片容量:", cap(Ids2))
	fmt.Println("Ids2切片内容:", Ids2)

结果如下:

Ids1切片长度: 10
Ids1切片容量: 10
Ids1切片内容: [0 0 0 0 0 0 0 0 0 0]
Ids2切片长度: 0
Ids2切片容量: 10
Ids2切片内容: []

      通过打印结果我们发现,第一种初始化的方式,同时定义了lencap,导致切片默认分配了零值,当我们使用append的时候,由于新元素超过了cap(10),因此就发生了扩容,导致写入的元素堆到了后面。

      第二种初始化的方式,我们定义了cap,但是len=0,这样就不会默认给元素赋零值,因为切片实际上是没有任何元素的。此时append就可以把元素加进去,填充切片。

3、正确的用法

(1)下标指定
Ids1 := make([]int64, 10)
for k, v := range xxxx {
   Ids1[k] =  v.ids1
}
(2) 使用另一种初始化方式
Ids1 := make([]int64, 10)
Ids2 := make([]int64, 0, 10)
for _, v := range xxxx {
   Ids1 = append(Ids1, v.ids1)
   Ids2 = append(Ids2, v.ids2)
}

//打印结果如下:
 
 Ids1:([0 0 0 0 0 0 0 0 0 0 393 394 395 396 397 398 399 400 401 402])
 Ids2:([183 184 184 185 185 186 187 188 189 190])

      看似简单的代码,实际上也暗藏玄机。博主一开始也被误导了,代码看似提前分配了容量,实际上没鸟用,扩容跑不了,而且前10个元素为0,这个时候万一靠下标获取元素,直接出bug没商量。

end

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

铁柱同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值