您所在的位置:首页 / 知识分享

Go 每日一练之函数传值

2020.07.28

1041

Go 中函数传参仅有【值】传递一种方式,【值】传递一种方式,【值】传递一种方式(重要事说三遍)。

在Golang 中函数传参仅有值传递一种方式,但是跟c++或者PHP的不同,并没有引用传值,没有将实际参数的地址传递到函数中。

例如:

i :=3
i1 := &i  

此时i1是指针变量,它有自已内存地址,存储的值为 指针类型 *int=xxxxx  xxx为i变的内存地址,使用 c :=*i1  可以返回i1指向变量的值, 使用 *i1  =5 可修改i1指向变量的值。

另外i1指针变量本身的地址可以使用 &来获取  &i1。


 有如下函数:

func c() (i int) {
i = 3
i1 := &i //&操作符(前缀)来获取变量的内存地址(取地址操作)
//变量 i 的地址使用变量 i1 进行接收,i1的类型为*T,称做 T 的指针类型,*代表指针。
fmt.Printf("i变量本身地址为:%p\n", &i)     //0xc00000c2e0
fmt.Printf("i1指针变量本身地址为:%p\n", &i1) //0xc000006028

fmt.Printf("i1指针变量存值为:%s\n", i1)    //*int=0xc00000c2e0
fmt.Printf("i1指针变量指向存值为:%s\n", *i1) //3

defer func(i2 *int) {
fmt.Printf("i2指针变量本身地址为:%p\n", &i2) //0xc000006038
fmt.Printf("i2指针变量指向存值为:%s\n", *i2) //:3
fmt.Printf("i2指针变量存值为:%s\n", i2)    //*int=0xc00000c2e0
*i2 = 5                             //*操作符的根本意义就是操作指针指向的变量

}(i1)
return
}

实参i1 与 形参i2 的地址各自互不相关,说明在参数传递中发生了值拷贝,但他们指向了变量i的地址...所以可以修改i值,在函数 defer 中,形参 i2 的地址与实参 i1 的地址并不一样,但是他们在内存中的值都是变量 i 的地址,因此可以通过指针相关的操作来改变i的值。

那么指针变量pa传给函数的形参p后,形参将会是它在栈上的一份拷贝,他们本身将各自拥有不同的地址,但是二者的值是一样的(都是变量a的地址)。

最后要说的是, 引用类型和传引用是两个概念。在Golang中  slice、map、channel都是引用类型。通过传递给函数时,是可以被修改的。

如下:

func change(qqs map[string]string) {
 qqs["aa"] = "ccc"
}

 qq := make(map[string]string)
 qq["aa"] = "11"
 qq["bb"] = "22"

 fmt.Print(qq)
 change(qq)
 fmt.Print(qq)
上程序会输出:

map[aa:11 bb:22]

map[aa:ccc bb:22]


总结:在Golang 中函数传参仅有值传递一种方式引用类型和传引用是两个概念。



相关新闻

GO目录结构

2020.01.07

1282

一般的编程语言往往对工程(项目)的目录结构是没有什么规定的,但是Go语言却在这方面做了相关规定,本节我们就来聊聊Go语言在工程结构方面的有关知识。

supervisor程序监控配置,参数及中文详解

2020.12.26

1366

supervisor 程序监控

你的iPhone XS/XS Max/XR 适配尺寸已上线啦 原创文章

2018.09.25

6728

新机型一发布,设计师们就要考虑适配问题。关于适配的文章看了几篇了? 眼花缭乱否? 不如看一篇简单直接的!