go切片参数传递用值还是指针

简介: go切片参数传递用值还是指针

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站

Go 中常用的切片 slice 数据结构是动态数组,切片长度并不固定,在容量不足的时候会自动扩容。

切片实质上是对一个底层数组的抽象视图,由 Go 运行时维护。在运行时,切片由如下的 SliceHeader 结构体表示,其中 Data 字段是指向底层数组的指针,Len 表示当前切片的长度,而 Cap 表示当前切片的容量,也就是 Data 数组的大小。

type SliceHeader struct {
    Data uintptr
    Len  int
    Cap  int
}

切片作为参数入参

我们知道 slice 是一个指针类型,所以我们可能会习惯性地认为:传递切片,等同于传递指针,函数内部对切片的修改,将会影响到函数外部的切片。这一习惯性认知在大部分情况下都是正确的,如以下代码所示:在 test 函数中修改切片,外部的 TestSlice 受到了影响。

func test(s []string) {
  for i := 0; i < len(s); i++ {
    s[i] = "b"
  }
}

func TestSlice(t *testing.T) {
  s := []string{"a", "b"}
  fmt.Println(s)
  test(s)
  fmt.Println(s)
}

输出:

[a b]
[b b]

我们对上面的代码做一些修改,在调用函数的时候触发切片的扩容机制,然后再看看输出:

func test1(s []string) {
  s = append(s, "b1")

  for i := 0; i < len(s); i++ {
    s[i] = "b"
  }
}

func TestSlice1(t *testing.T) {
  s := []string{"a", "b"}
  fmt.Println(s)
  test1(s)
  fmt.Println(s)
}

输出:

[a b]
[a b]

我们可以发现,test1 里面对切片的修改并没有完全影响到外部的切片。

原因

在 Go 中,函数参数传递机制为 值拷贝

将切片做为函数参数传递,实际上是拷贝了 SliceHeader 结构体传入参数,结构体包含了指向底层数组的指针,因此在函数内部修改切片,操作的底层数组是一样的。

但是如果函数内的切片触发了切片扩容(如:使用 append 追加元素),Go 运行时会为切片分配一块新的内存空间并将原切片的所有元素拷贝过去,函数内部切片的底层数组指针指向了 新分配 的内存空间,而函数外部切片底层数组指针仍指向 分配前 的地址空间,由此出现了内外切片不一致的情形。

建议

  • 操作不涉及切片容量变化,直接传递切片
  • 操作涉及切片容量变化,且需要反馈给调用放,传递切片指针。


目录
相关文章
|
16天前
|
存储 Go
|
16天前
|
Java Go 数据处理
go语言使用切片而非数组
【10月更文挑战第18天】
9 1
|
15天前
|
Go
|
29天前
|
存储 安全 Go
Go语言切片:从入门到精通的深度探索###
本文深入浅出地剖析了Go语言中切片(Slice)这一核心概念,从其定义、内部结构、基本操作到高级特性与最佳实践,为读者提供了一个全面而深入的理解。通过对比数组,揭示切片的灵活性与高效性,并探讨其在并发编程中的应用优势。本文旨在帮助开发者更好地掌握切片,提升Go语言编程技能。 ###
|
2月前
|
Go 索引
Go to Learn Go之切片
Go to Learn Go之切片
28 1
|
2月前
|
存储 Go
Go to Learn Go之指针
Go to Learn Go之指针
26 0
|
2月前
|
存储 Go
Go: struct 结构体类型和指针【学习笔记记录】
本文是Go语言中struct结构体类型和指针的学习笔记,包括结构体的定义、成员访问、使用匿名字段,以及指针变量的声明使用、指针数组定义使用和函数传参修改值的方法。
|
2月前
|
编译器 Go 索引
Go数组、多维数组和切片(动态数组),及常用函数len(),cap(),copy(),append()在切片中的使用
本文介绍了Go语言中数组、多维数组和切片(动态数组)的基本概念和操作,包括数组的定义、初始化、访问,多维数组的定义和访问,以及切片的创建、使用和扩容。同时,还讲解了切片中常用的函数len()、cap()、copy()和append()的使用方法。
|
3月前
|
存储 缓存 Go
在 Go 中如何复制切片和映射?
【8月更文挑战第31天】
80 0
|
3月前
|
存储 Go 数据处理
C 数组和 Go 切片的区别详解
【8月更文挑战第31天】
36 0