golang的slice问题

查看:98
本文介绍了golang的slice问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

s1 := []int{1, 2, 3, 4}
s2 := []int{-1, -2, -3}

fmt.Println(append(s1[:1], s2...))

fmt.Println(s1)

打印的结果:

[1 -1 -2 -3]
[1 -1 -2 -3]

弄不明白的是:为什么s1的值也变了?

解决方案

因为append函数并不保障slice是否被修改,也就是说append可能会修改slice,也可能不修改,所以使用append有两个原则:

  1. append函数调用后,应该使用返回值作为结果。

  2. append函数调用后,不应该再使用实参传入的slice。
    所以使用append函数一般都是s = append(s,elem1)这种用法,也就是把结果重新赋值给原来的slice。

append函数之所以有这个表现,是因为slice的底层存储依赖于底层数组(underlying array),用你的例子来给你说明一下:
你的s1初始化的值是[]int{1, 2, 3, 4},它的len和cap都是4,所以它的底层数组是一个长度为4的数组[4]int{1,2,3,4}
基于slice的特点,s1[:1]和s1是共享底层数组的,所以s1[:1]这个slice的改变是会影响到underlying array的。

If it has sufficient capacity, the destination is resliced to accommodate the new elements. If it does not, a new underlying array will be allocated.

append函数在填充elem1,elem2的时候会先判断slice的cap是否能容纳所有追加的值,这个计算方式是从slice的尾部计算的,在你的例子里,slice的尾部是第一个元素,后面的容量恰好可以满足3个元素,所以它不会申请新的底层数组,而会直接使用原有的底层数组作为存储,这也就把原本的底层数组改成了[1 -1 -2 -3],由于s1的存储依赖于这个底层数组,自然也就变成了[1 -1 -2 -3]

如果把你的例子改成append(s1[:1],1, s2...),或者改成append(s1[1:2], s2...),你就会发现s1没有被改变,这是因为容量不能容纳所有追加元素,append会申请一个新的底层数组用来存储,也会返回一个新的slice,这不会影响到原本的底层数组,也就不会影响到原本的slice。

所以使用s = append(s,elem1)是一个好习惯,尽量使用这个用法。

这篇关于golang的slice问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆