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天前
|
存储 安全 Java
Go 指针
该文章深入探讨了Go语言中的指针概念,包括指针的获取、使用、限制以及如何安全地返回局部变量的地址,同时讨论了`unsafe.Pointer`在打破指针限制方面的作用。
12 3
|
11天前
|
存储 缓存 Go
在 Go 中如何复制切片和映射?
【8月更文挑战第31天】
26 0
|
11天前
|
存储 Go 数据处理
C 数组和 Go 切片的区别详解
【8月更文挑战第31天】
20 0
|
11天前
|
存储 安全 Go
深入理解 Go 语言中的指针类型
【8月更文挑战第31天】
8 0
|
11天前
|
存储 Go 开发者
掌握Go语言中的指针
【8月更文挑战第31天】
6 0
|
14天前
|
Go 计算机视觉
Go从入门到放弃之指针
Go从入门到放弃之指针
|
14天前
|
人工智能 编译器 Go
Go从入门到放弃之数组、切片
Go从入门到放弃之数组、切片
|
27天前
|
监控 Serverless Go
Golang 开发函数计算问题之Go 语言中切片扩容时需要拷贝原数组中的数据如何解决
Golang 开发函数计算问题之Go 语言中切片扩容时需要拷贝原数组中的数据如何解决
|
Go
Go语言的切片slice基本操作
感觉比数组好用,首选。 package main import ( "fmt" ) //main is the entry of the program func main() { slice1 := make([]string, 5) slice2 := ma...
1021 0
|
1天前
|
程序员 Go PHP
为什么大部分的 PHP 程序员转不了 Go 语言?
【9月更文挑战第8天】大部分 PHP 程序员难以转向 Go 语言,主要因为:一、编程习惯与思维方式差异,如语法风格和编程范式;二、学习成本高,需掌握新知识体系且面临项目压力;三、职业发展考量,现有技能价值及市场需求不确定性。学习新语言虽有挑战,但对拓宽职业道路至关重要。
22 10