值传递&引用传递

1. 值类型

定义:变量直接指向存在内存中的值,我们称之为值类型。

  • 值类型的变量的值存储在栈中

  • 值类型,将一个变量赋值给另一个变量,称为值拷贝

package main
 
import "fmt"
 
func main(){
    var num1,num2 int
    num1 = 10
    num2 = num1 // 值类型赋值操作
 
    fmt.Println(num1,num2) // 10 10
 
    num1 = 20
    fmt.Println(num1,num2) // 20 10
}

2. 指针类型

一个变量指向内存中值所在的内存地址,我们称这个变量为指针类型

go 语言中的指针与C/C++ 中的指针用法是一样的,只是出于安全性的考虑go增加了: 1、不同类型的指针不能互相转化 2、任何普通指针类型*T和uintptr之间不能互相转化 3、指针变量不能进行运算

package main

import "fmt"

func main(){
    var num int = 100
    var ptr *int  // 类型前 加 * 表示这是指针类型,指针类型的初始值为nil ,和其他语言的NUll,None一样
    ptr = &num // & 取num 变量的内存地址。 因为ptr 是指针,指向的是内存地址,所以需要赋值操作的是内存地址
    fmt.Println("ptr 指针的值:",ptr)
    fmt.Println("*ptr 指针的值:",*ptr) // * 取指针内存地址所指向的值

    num = 200
    fmt.Println("*ptr 指针的值:",*ptr)

}

3. 引用类型

在go语言中目前引用类型有: 切片、map、chan、func 空指针(引用): nil

4. 值接受者与指针接受者

1. 值接受者

值接受者可以给接收值、也可以接收指针,因为go会对接收的指针进行解引用。但是!variable传递进函数的只是副本,他们都是在variable的副本上进行操作,并不影响 variable 的原本的值。

func ( variable type )Name ( InputParam ) ( OutputParam )

2. 指针接受者

指针接收者接收的是variable的值的地址,也就是说func修改了值的时候会影响 variable 原本的值。

(variable *type)func()

5. 指针与引用

  1. 指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个“存储单元”,即指针是一个实体;而引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已。
  2. 可以有const指针,但是没有const引用;
  3. 指针可以有多级,但是引用只能是一级(int **p;合法 而 int &&a是不合法的)
  4. 指针的值可以为空,但是引用的值不能为NULL,并且引用在定义的时候必须初始化;
  5. 指针的值在初始化后可以改变,即指向其它的存储单元,而引用在进行初始化后就不会再改变了,从一而终。
  6. ”sizeof引用”得到的是所指向的变量(对象)的大小,而”sizeof指针”得到的是指针本身的大小;
  7. 指针和引用的自增(++)运算意义不一样;
  8. 引用是操作受限了的指针(仅容许取内容操作)。
int i = 5;
int j = 6;
int &k = i;
k = j; // k 和i 的值都变成了6

6. 指针引用&值引用

  1. 值引用赋值 比如 a:=b,这样修改a.name=“ls”,不会影响到b.name,值引用是复制结构体,开辟一块新的内存空间, a只是b的一个副本,而不是指向b的引用。
  2. 指针引用赋值 比如 a:=&b ,这样修改a.name=“ls”,会影响到b.name,指针引用是指向结构体内存地址的引用,同一块内存空间

总结1:值引用,两个变量值是独立的,而指针引用则会互相影响,因为他们都指向同一块内存地址。

总结2:值引用只是复制的一个副本,不是指向内存地址的引用;指针引用,指针是指向内存地址的引用,因此使用它操作的不是结构体的副本而是本身

总结3:指针引用的时候,比如 b:=&a, 此时b是指针,因此必须使用*b对其进行引用取其内容的值。

0%