Go 参数传递
Go参数传递
在面试中,经常会被问起,这门语言的参数传递是值传递还是引用传递,当然,大部分情况下我们都会提前准备,有恃无恐,但还是希望能够精益求精嘛,所以针对Go语言来分析,Go传参是值传递还是引用传递。那首先,我们先来了解什么是值传递,什么是引用传递。
值传递
值传递就是函数传递的是传进来参数的一个副本。换个说法就是函数内部修改传入参数的值是函数外部传入值得一个拷贝,所以你在函数内部对这个值进行修改也不会影响外部该参数的值,的确很难表达,看个案例:
package main
import "fmt"
func modify(a int){
a = 10
}
func main(){
a := 20
fmt.Println(a)
modify(a)
fmt.Println(a)
}
输出:
20
20
很直观,参数a在进入函数后并没有被改变,我们还可以看看两个内存地址是否相同
package main
import "fmt"
func modify(a int){
fmt.Println(&a)
a = 10
}
func main(){
a := 20
fmt.Println(&a)
modify(a)
}
输出为:
0xc000052080
0xc000052088
可以看到两个内存地址并不一样,这就对了,可以说明modify
中的参数a,并不是主函数中的变量a,而是a的一个拷贝而已,所以在函数中修改的也是拷贝a的值,对函数外的这个a并没有改动。
这个时候,我们就会使用指针来修改值,指针案例:
func main() {
i:=10
ip:=&i
fmt.Printf("原始指针的内存地址是:%p\n",&ip)
modify(ip)
fmt.Println("int值被修改了,新值为:",i)
}
func modify(ip *int){
fmt.Printf("函数里接收到的指针的内存地址是:%p\n",&ip)
*ip=1
}
输出:
原始指针的内存地址是:0xc000006028
函数里接收到的指针的内存地址是:0xc000006038
int值被修改了,新值为: 1
可以看到两次内存地址也是不一样的,所以其实指针也是值传递,但是指针保存的是内存地址,而在函数中修改语句"*ip=1",其实是在修改变量i内存地址对应的值,那自然就是能够修改的。
引用传递
Go语言其实并没有引用传递,上面的例子可以证明如果内存地址不同自然就是值传递,那内存地址相同就是引用传递。
我们再通过Map类型进行验证,Map类型可以通过函数修改内容,但是他没有明显的指针。
func modify(p map[string]int){
fmt.Printf("函数里接收到map的内存地址是:%p\n",&p)
p["张三"] = 20
}
func main(){
person := make(map[string]int)
person["张三"] = 56
fmt.Printf("原始map的内存地址是:%p\n",mp)
modify(person)
fmt.Println("map值被修改了,新值为:",person)
}
输出:
原始map的内存地址是:0xc00007e018
函数里接收到map的内存地址是:0xc00007e028
map值被修改了,新值为: map[张三:20]
发现两个内存地址是不一样的,所以这又是一个值传递,那为什么没有使用指针却修改了Map的内容?
查看一下map源码
func makemap(t *rtype, cap int) (m unsafe.Pointer)
我们发现这个方法返回的是m unsafe.Pointer
继续查看一下unsafe.Pointer
类型是什么?
type Pointer *ArbitraryType
返回的还是一个指针,所以我们可以得出map的传递也是值传递。
结论
确认Go语言中所有的传参都是值传递。但是传递的类型如果是int、string、struct等这些,那在函数中无法修改原参数内容数据;如果是指针、map、slice、chan等这些,在函数中可以修改原参数内容数据。
Go 参数传递的更多相关文章
- js学习之函数的参数传递
我们都知道在 ECMAScript 中,数据类型分为原始类型(又称值类型/基本类型)和引用类型(又称对象类型):这里我将按照这两种类型分别对函数进行传参,看一下到底发生了什么. 参数的理解 首先,我们 ...
- kettle中含有参数传递的定时任务
(1)新建一个作业(新建->作业),并在控制面板右键: (2)设置一个命令参数: (3)把作业的参数传递给转换: (4)在转换中右键设置转换属性: (5)接收作业中设置的传递参数: (6)参数的 ...
- Java基础知识笔记(七:接口、变量作用域和参数传递)
一.接口 Java语言不允许一个子类拥有多个直接父类,即任何子类只能有一个直接父类.但允许一个类实现多个接口,即在定义类的接口名称列表中可以包含1个或多个接口名称,从而实现多重继承的特性.接口的定义格 ...
- shell 脚本之获取命令输出字符串以及函数参数传递
在ubuntu 14.04之后,所有的U盘挂载也分用户之分,最近很多操作也和U盘有关,所以就研究了一上午shell脚本函数以及字符串操作的方法. 字符串操作: 获取他的命令输出比较简单,打个简单的比方 ...
- 【GoLang】golang 闭包 closure 参数传递的蹊跷!
结论: 闭包函数可以直接引用外层代码定义的变量, 但是,注意,闭包函数里面引用的是变量的地址, 当goroutine被调度时,改地址的值才会被传递给goroutine 函数. 介绍 go的闭包是一个很 ...
- JQuery Mobile 页面参数传递
在单页模版中使用基于HTTP的方式通过POST和GET请求传递参数,而在多页模版中不需要与服务器进行通信,通常在多页模版中有以下三种方法来实现页面间的参数传递. 1.GET方式:在前一个页面生成参数并 ...
- Java 中的值传递和参数传递
Java中没有指针,所以也没有引用传递了,仅仅有值传递不过可以通过对象的方式来实现引用传递 类似java没有多继承 但可以用多次implements 接口实现多继承的功能 值传递:方法调用时,实际参数 ...
- 【Python学习】函数参数传递方法四种(位置,关键字,默认值,包裹位置,包裹关键字传递)
1. 位置传递: #--coding:utf-8-- def send(name,address): return 'package is sent to %s, located in %s' %(n ...
- JAVA反射参数传递
引用:http://fish2700.blog.163.com/blog/static/130713192009103035723281/ 使用Method反射调用函数时,我们通常会遇到以下几种情况: ...
- [蟒蛇菜谱]Python函数参数传递最佳实践
将函数作为参数传递,同时将该函数需要的参数一起传递.可参考threading.Timer的处理方式: class threading.Timer(interval, function, args=[] ...
随机推荐
- C# 监测每个方法的执行次数和占用时间(测试4)
今天也要做这个功能,就百度一下,结果搜索到了自己的文章.一开始还没注意,当看到里面的一个注释的方法时,一开始还以为自己复制错了代码,结果仔细一看网页的文章,我去,原来是自己写的,写的确实不咋地. 把自 ...
- 1-移远GSM/GPRS M26 模块 Mini板 开发板(使用说明)
板子预览 引脚说明 供电 关于串口电压匹配引脚: 上面一版朋友测试反应的问题 (上面的内容不删除,因为已经出售了1套) 1,源码开发完以后,烧录完成 PWRKEY按键不能使用了,需要断电上电,那么就需 ...
- 探索性数据分析(Exploratory Data Analysis,EDA)
探索性数据分析(Exploratory Data Analysis,EDA)主要的工作是:对数据进行清洗,对数据进行描述(描述统计量,图表),查看数据的分布,比较数据之间的关系,培养对数据的直觉,对数 ...
- e3s10 网络管理
1. host上设置 iptables -t nat -A POSTROUTING -o eno1 -j MASQUERADE # https://www.unixtutorial.org/how-t ...
- Luogu5206 【WC2019】数树 【容斥,生成函数】
题目链接 第一问白给. 第二问: 设 \(b=y^{-1}\),且以下的 \(Ans\) 是除去 \(y^n\) 的. 设 \(C(T)\) 是固定了 \(T\) 中的边,再连 \(n-|T|-1\) ...
- 02-线性结构4 Pop Sequence (25 分)
Given a stack which can keep M numbers at most. Push N numbers in the order of 1, 2, 3, ..., N and p ...
- mac 下的 tree 命令 终端展示你的目录树结构
相信很多使用过Linux的用户都用过tree命令,它可以像windows的文件管理器一样清楚明了的显示目录结构.mac 下使用 brew包管理工具安装 tree 前提:安装了homebrew(安装指令 ...
- GoCN每日新闻(2019-10-10)
GoCN每日新闻(2019-10-10) GoCN每日新闻(2019-10-10) 1. Go语言源码阅读之bytes.Buffer http://www.pengrl.com/p/60618/ 2. ...
- Android中如何动态添加碎片
Android中的开发需要兼容手机和平板,两个方面.这就引入了碎片的概念.(注意:这里用的Fragment强烈建议使用support-v4库中的Fragment) 碎片:是一种可以嵌入在活动当中的UI ...
- Spring Cloud Ribbon---微服务调用和客户端负载均衡
前面分析了Eureka的使用,作为服务注册中心,Eureka 分为 Server 端和 Client 端,Client 端作为服务的提供者,将自己注册到 Server 端,Client端高可用的方式是 ...