Go篇|参数传递:值、引用、指针的区别

1,503 阅读3分钟

这是我参与更文挑战的第10天,活动详情查看: 更文挑战

本节主要学习,函数或者方法在传递参数的过程中,遇到值类型,指针类型时会发生什么情况,并从demo入手深入了解其原理。

从Demo入手,运行以下demo更深刻的了解其内部的原理

type person struct {
	name string
	age  int
}

// 
func updatePerson(p person) {
	p.name = "jasen"
	p.age = 20
}

func main() {
	p := person{"南吕", 18}
	updatePerson(p)  // updatePerson(&p)
	fmt.Println("After Update")
	fmt.Println("name:", p.name, "age:%d", p.age)
}

// 将updatePerson函数的参数改成指针参数时,
func updatePerson(p *person){
  	p.name = "jasen"
	  p.age = 20
}

运行结果:

image.png

调用updatePerson后,重新输出时,name和age都不变。

但是,如果将函数的参数改成指针参数时,重新运行输出的结果就是变化了

image.png

上述的demo,就是值类型参数和指针类型参数的区别

变量都存储在内存中,每个内存都有一个内存地址,如果想要修改内存中的数据,需要找到这个内存地址。

值类型

函数传递的参数是值类型。

type person struct {
	name string
	age  int
}

func updatePerson(p person) {
	fmt.Printf("update函数内:p的地址:%p\n",&p)
	p.name = "jasen"
	p.age = 20
}

func main() {
	p := person{"南吕", 18}
	fmt.Printf("main函数内:p的地址:%p\n",&p)
	updatePerson(p)
	fmt.Println("After Update==> name:", p.name, "age:", p.age)
}

image.png

现象:p的内存地址不一致,说明main函数中的变量p和updatePerson函数的变量p不是同一个。

原因:函数传参是值传递,值传递指的是传递原来的数据的复制品,不是数据本身。他们的内存地址是不一致的,但是内存中存储的数据是一样的

值类型:struct结构体,浮点型,整型,字符串,布尔类型,数组

指针类型

指针类型的变量是实际是内存地址,所以如果在函数参数传递是指针类型的话,则相当于传递内存地址,那将传递的是同一个变量。

修改上述demo,从传参为指针类型的demo来观察结果:

type person struct {
	name string
	age  int
}

func updatePerson(p *person) {
	fmt.Printf("update函数内:p的地址:%p\n",p)
	p.name = "jasen"
	p.age = 20
}

func main() {
	p := person{"南吕", 18}
	fmt.Printf("main函数内:p的地址:%p\n",&p)
	updatePerson(&p)
	fmt.Println("After Update==> name:", p.name, "age:", p.age)
}

image.png

现象:内存地址是同一个,则p对应的数据也是同一份数据

原因:传递指针类型,即内存地址,通过内存地址可找到原数据的那块内存,那么修改它就等于修改了原数据

指针类型:加*都是表示指针类型

引用类型

严格来说,Go语言中没有引用类型。为便于理解,将其称为引用类型。

只要通过关键字make声明的变量都可称为应用类型。比如map、chan、slice切片、接口、函数。

上述demo我们将其换成map,并打印其内存地址。

func main(){
  stuMap := make(map[string]int)
	stuMap["nanlv"] = 18
	fmt.Printf("main函数内:stuMap的地址:%p\n",stuMap)
	updateMap(stuMap)
	fmt.Println("nanlv的年龄为",stuMap["nanlv"])
}

func updateMap(stuMap map[string]int){
	fmt.Printf("updateMap函数内:stuMap的地址:%p\n",stuMap)
	stuMap["nanlv"] = 30
}

image.png