关于后端:值类型与引用类型值传递与引用传递

6次阅读

共计 1545 个字符,预计需要花费 4 分钟才能阅读完成。

值传递和援用传递

Go 语言参数传递是传值还是传援用

一文整得明明白白~

Go 全部都是 值传递 ,不存在 援用传递

值传递 是原始值 copy 出一份正本,而后传递;援用传递 是间接传原始值的指针;

值传递并非不能批改原始值,当原始值是援用类型时(指针、map、slice、chan 等这些),值传递就能够批改原始值(值传递传的指针是原始值指针的正本,但两个指针都指向同一个地址)


值类型和援用类型

slice,map,channel,interface,func 这 5 种数据类型 是援用类型,都 (或者至多某个字段) 是指针 (援用类型能够看作是对指针的封装)

(应用 make 函数创立的 map,channel 其实都是一个指针,slice 是其构造体 SliceHeader 的 Data 字段是指针)

// SliceHeader is the runtime representation of a slice.
// It cannot be used safely or portably and its representation may
// change in a later release.
// Moreover, the Data field is not sufficient to guarantee the data
// it references will not be garbage collected, so programs must keep
// a separate, correctly typed pointer to the underlying data.
type SliceHeader struct {
    Data uintptr
    Len  int
    Cap  int
}

int、float、bool、array、sturct 是值类型

string 比拟有争议,感觉是值类型,但有种说法也是援用类型

几种说法

说法 1:“援用类型保留在堆上,值类型保留在栈上”?

这种说法是不精确的

首先不要纠结字面意思,Java 中(byte、short、int、long、float、double)、字符型(char)、布尔型(boolean)这些根本类型数据间接保留在栈中,而类、接口、数组数据是保留在堆中,栈只是保留一个指向堆内存的指针。

一文理清 Go 援用的常见纳闷


浅拷贝与深拷贝

探讨值传递和援用传递时, 其实就是看值类型变量和援用类型变量作为函数参数时, 批改形参是否会影响到实参

在 Go 语言中除了 五个援用类型 , 其余都是值类型:

  • slice
  • map
  • channel
  • interface
  • func()

援用类型作为参数时, 称为浅拷贝, 形参扭转, 实参数追随变动. 因为传递的是地址, 形参和实参都指向同一块地址

值类型作为参数时, 称为深拷贝, 形参扭转, 实参不变, 因为传递的是值的正本, 形参会新开拓一块空间, 与实参指向不同

如果心愿值类型数据在批改形参时实参追随变动, 能够把参数设置为指针类型

Golang 根底(闭包、值传递与援用传递)

须要留神的是,在 Go 语言中,闭包外部援用内部变量时,实际上是援用了内部变量的地址。因而,闭包的行为相似于援用传递,而不是像个别的函数参数那样的值传递。

个别认为这种类型才是真正意义上的闭包(即不传参数进去)

package main

func main() {
    i := 1
    func() {
        i = 2
        print(i)
    }()

    print(i)
}

实际上,我把这种状况也认为是闭包:

package main

func main() {
    i := 1
    func(i int) {
        i = 2
        print(i)
    }(i)

    print(i)
}

即传参进去,那外面的改变就不会影响里面,里面的改变也不会影响外面(在传进去那一刻就定住了~)

当然如果这样,外面的改变还是会扭转里面的值

package main

func main() {
    i := 1
    func(k int) {
        i = 2
        print(i)
    }(i)

    print(i)
}

本文由 mdnice 多平台公布

正文完
 0