30

go语言中的slice一些使用注意事项

 4 years ago
source link: https://studygolang.com/articles/30551
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

golang中的slice很灵活,功能也很强悍,不过对于初学者来说会容易被它坑到,此篇文章就尽量提及到使用slice的一些容易容易出错的地方,以下示例使用的golang版本为1.14.2。

作为参数传递

在go语言中的方法的参数都为值传递,切片也不例外,但是切片有一个指向数据地址的指针,所以就算是值传递,如果改变切片中的已有元素数据,也有可能影响到原有的切片

为什么是可能呢?我们来看下面的代码

func test(a []int) {
    a = append(a, 1)
    a[0] = 2
}

func main() {
    s1 := make([]int, 1, 1)
    log.Printf("%v\n", s1) // [0]
    test(s1)
    log.Printf("%v\n", s1) // [0]
}

这里的s1变量并没有被影响到数据;那么我们再来看下面的代码

func test(a []int) {
    a = append(a, 1)
    a[0] = 2
}

func main() {
    s1 := make([]int, 1, 2)
    log.Printf("%v\n", s1) // [0]
    test(s1)
    log.Printf("%v\n", s1) // [2]
}

咦,这里的s1就已经被改变了,这是为什么呢?我们可以看看append方法的注解,如果目的切片容量足够,那么会直接添加到原切片指向的数据地址再返回一个拥有新长度和原数据地址的新切片,所以直接修改原切片长度内的数据会影响到原切片数据;目的切片容量不足时才会另外申请空间,此时新切片拥有新的数据地址,所以不会影响到原有切片。

注意append总是会返回一个新切片;原切片容量足够时,新切片指向的数据地址不变,依然是原切片指向的数据地址

作为方法返回值

当切片作为方法返回值时也有几点值得注意

只返回了一个切片的一部分时,并不会复制数据,而是直接指向原地址

这样的话如果一直在引用返回的切片时,整个切片都不会被释放,一直在内存中

如果返回的切片是一个很多地方都可以获取到的同一切片变量,比如

var a = []int{1, 2, 1}

func GetA() []int{
    return a
}

那么此时也没有真正做到值传递,外面的修改可能会影响到a,并且如果有多个协程获取并修改的话,还有并发同步问题

我们可以以下面的方式返回一个指向新地址的slice解决上面的问题,做到真正的值传递

func GetA() []int{
    return append([]int{}, a...)
}

nil切片

一个nil切片也是可以使用len()方法的,此时为0,如果不需要判断切片是否为nil则直接使用len()方法即可

有疑问加站长微信联系

iiUfA3j.png!mobile

Recommend

  • 43
    • hexo.hainuo.info 6 years ago
    • Cache

    JWT使用一些注意事项 | 海诺博客

  • 57
    • studygolang.com 6 years ago
    • Cache

    Go语言中defer的一些坑

    defer语句是Go中一个非常有用的特性,可以将一个方法延迟到包裹该方法的方法返回时执行,在实际应用中,defer语句可以充当其他语言中try…catch…的角色,也可以用来处理关闭文件句柄等收尾操作。 defer触发时机 A "d...

  • 21
    • zhuanlan.zhihu.com 4 years ago
    • Cache

    go语言中的slice

    go语言中的slice红日照小池反对资本主义,反对官僚,反对帝国主义go语言中有两种“...

  • 3
    • studygolang.com 3 years ago
    • Cache

    Go 语言中的一些非常规优化

    Go 语言中的一些非常规优化 Xargin · 大约12小时之前 · 127 次点击 · 预计阅读时间 5 分钟 · 大约8小时之前 开始浏览    

  • 9
    • segmentfault.com 3 years ago
    • Cache

    SAP UI5 使用 CSS 的一些注意事项

    CSS Styling Issues本节列出了 SAPUI5 中与 CSS 样式相关的一些最重要的规则。SAP...

  • 6

    Go语言中 defer 使用场景及注意事项,你是要注意的! goCenter · 11天之前 · 156 次点击 · 预计阅...

  • 7
    • blog.thinkeridea.com 3 years ago
    • Cache

    【Go】slice的一些使用技巧

    slice 是 Go 语言十分重要的数据类型,它承载着很多使命,从语言层面来看是 Go 语言的内置数据类型,从数据结构来看是动态长度的顺序链表,由于 Go 不能直接操作内存(通过系统调用可以实现,但是语言本身...

  • 6
    • blog.xpgreat.com 3 years ago
    • Cache

    使用Hugo的一些注意事项

    一些在使用Hugo时发现的小技巧或问题及解决方法,会持续更新。 如何插入本地图片? 一直不知道怎样插入本地图片,查找后得知,在site目录下的static目录就是存放静态文件的地方,可以在下面创建一个media

  • 7
    • sunqi.site 2 years ago
    • Cache

    2.5 Go语言中的切片(Slice)

    2.5 Go语言中的切片(Slice) 2022-06-18  约 1062 字   预计阅读 3 分钟   1 次阅读  与数组很相似,但是Slices长度是可变的,操作方式与Python的list类型相似,例如新增一个元素。区别在于Slices通过指针...

  • 7

    在Go语言中,init()函数是一种特殊的函数,用于在程序启动时自动执行一次。它的存在为我们提供了一种机制,可以在程序启动时进行一些必要的初始化操作,为程序的正常运行做好准备。 在这篇文章中,我们将详细探讨init()函数的特点...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK