函数的传递参数方式:

  • 传递结构体时:会拷贝结构体中的全部内容;
  • 传递结构体指针时:会拷贝结构体指针;
  • 将指针作为参数传入某个函数时,函数内部会复制指针,也就是会同时出现两个指针指向原有的内存空间,所以 Go 语言中传指针也是传值

Go 语言的整型和数组类型都是值传递的

  也就是在调用函数时会对内容进行拷贝。需要注意的是如果当前数组的大小非常的大,这种传值的方式会对性能造成比较大的

 

所以在使用函数的时候 传递数组或者内存占用非常大的结构体时,我们应该尽量使用指针作为参数类型来避免发生数据拷贝进而影响性能

golang的函数

  1. 通过堆栈传递参数,入栈的顺序是从右到左,而参数的计算是从左到右;
  2. 函数返回值通过堆栈传递并由调用者预先分配内存空间;
  3. 调用函数时都是传值,接收方会对入参进行复制再计算;

Go 语言选择了传值的方式,无论是传递基本类型、结构体还是指针,都会对传递的参数进行拷贝

数组:

  数组和字符串的一些简单越界错误都会在编译期间发现,例如:直接使用整数或者常量访问数组;但是如果使用变量去访问数组或者字符串时,编译器就无法提前发现错误,我们需要 Go 语言运行时阻止不合法的访问:数组和字符串的一些简单越界错误都会在编译期间发现,例如:直接使用整数或者常量访问数组;但是如果使用变量去访问数组或者字符串时,编译器就无法提前发现错误,我们需要 Go 语言运行时阻止不合法的访问: 

runtime.panicIndexruntime.goPanicIndex
slice:
intinterface{}
reflect.SliceHeader
DataLenCapData

Go 语言中包含三种初始化切片的方式:

make
runtime.makesliceruntime.mallocgc

 

append
/internal/gc.state.appendappend

 

runtime.growslice
slice = append(slice, 1, 2, 3)appendcompile/internal/gc.state.append

  是否覆盖原变量的逻辑其实差不多,最大的区别在于得到的新切片是否会赋值回原变量。

如果我们选择覆盖原有的变量,就不需要担心切片发生拷贝影响性能,因为 Go 语言编译器已经对这种常见的情况做出了优化。

拷贝切片

runtime.memmove

  切片的很多功能都是由运行时实现的,无论是初始化切片,还是对切片进行追加或扩容都需要运行时的支持,需要注意的是在遇到大切片扩容或者复制时可能会发生大规模的内存拷贝,一定要减少类似操作避免影响程序的性能。

 

相关文档: