golang 函数传多个参数_关于Golang中方法参数的传递

结构体声明

为了说明函数以及方法调用的过程,这里先定义一个struct,在下面的描述中会使用到它。

type Person struct {

Name string

Age uint16

}

普通函数中的参数传递

在Golang中,普通函数的行参如果是值类型,那么调用的实参也必须是实参,反之,如果函数行参是指针类型,那么传入的实参必须是地址。我们来看几个例子。

行参要求值传递

// 定义一个普通函数,要求值传递

func tell(person Person) {

fmt.Printf("Hi, my name's %v, I'm %v years old", person.Name, person.Age)

}

实参按照值的方式传递

// 调用函数,提供一个struct实例

person := Person{"Tom", 28}

tell(person) // Hi, my name's Tom, I'm 28 years old

我们可以看到,这种调用肯定是没有问题的,程序能够正常运行,当然这也是理所当然的

实参按照指针的方式传递

// 调用函数,提供一个struct实例的地址

person := Person{"Tom", 28}

tell(&person) // 编译错误:Cannot use '&person' (type *Person) as type Person

这会直接报编译错误,因为函数要求传入的是一个值,而函数调用给的却是一个地址,是不符合编译器要求的。

行参要求指针传递

这种情况,对于普通函数来讲,与上面的情形类似,即实参必须是地址,而不能是值。这里就不举例了。

方法中的参数传递

由上面我们可以看出,其实对于普通函数而言,参数的传递方式非常直接,而且容易理解。即,函数要求什么,调用的时候就给它什么。

但是对于方法调用来说,就会稍微复杂一些了(其实这种复杂性是为了给程序员提供方便,是不是感觉有点矛盾?哈哈)

对象是值的情况

首先,让我们把上面的函数改成一个方法,并且要求使用值对象的方式传递对象

func (person Person) tell() {

fmt.Printf("Hi, my name's %v, I'm %v years old", person.Name, person.Age)

}

按照我们对于普通函数的理解,调用该方法时,我们必须提供一个值对象,即

person := Person{"Tom", 28}

person.tell() // Hi, my name's Tom, I'm 28 years old

这种方式肯定工作,而且与普通函数的行为一致。但是,接下来,我要给该函数提供一个指针,我们来看

// 得到一个结构体指针

var person *Person = &Person{"Tom", 28}

person.tell() // Hi, my name's Tom, I'm 28 years old

从上面的运行结果,我们看到,这种调用也是被允许的,并没有报错。但是为什么?

这其实由于Go在编译的时候,会帮我们做一些事情,把代码转换成类似下面这个样子

(*person).tell()

即,会把指针类型先进行取值运算,然后再将其传递给方法。有了背后这一个转换,程序员不用在调用的时候先进行取值运算,再调用方法。从这个角度来讲,这种操作是不是给程序员提供了方便?

对象是指针的情况

类似的,如果方法要求传入的对象是指针类型,Go也允许我们传入值对象,Go在背后也是做了一个转换,即把传入的值,先进行地址运算,然后再将其传入方法中。下面详细描述一下。

假设我们的方法改成这样

// 该方法接收一个指针对象

func (person *Person) tell() {

fmt.Printf("Hi, my name's %v, I'm %v years old", person.Name, person.Age)

}

调用的时候,我们可以传入指针,也可以传入值。下面是传入值的情况

person := Person{"Tom", 28}

person.tell() // Hi, my name's Tom, I'm 28 years old

之所以这种调用没有报错,也是因为Go其实在编译的时候,进行了转换

(&person).tell()

在方法内修改对象的属性值,是否会影响原来的对象?

让我们来考虑一种情况,如果方法要求的对象是值对象,即

func (person Person) rename(newName string) {

person.Name = newName

}

而在调用这个方法的时候,调用的对象是个指针,那么下面的程序输出什么?

var person *Person = &Person{"Tom", 28}

person.rename("Jimmy")

person.tell()

答案是Hi, my name's Tom, I'm 28 years old。名字并没有改变,即,虽然我们传递了一个指针给rename方法,但是在rename方法里面对于person的修改,并没有反映到外部的person对象。也就是说,方法内的对象与方法外的对象之间是值拷贝。

接下来,我们再看另外一种情况,即,方法要求传入的对象是指针,但是调用的时候是在值对象上进行访问

func (person *Person) rename(newName string) {

person.Name = newName

}

person := Person{"Tom", 28}

person.rename("Jimmy")

person.tell()

输出的结果是Hi, my name's Jimmy, I'm 28 years old,也就是说名字改变了,即使我们在调用的时候传入的是值对象。

总结

如果方法要求的是值对象,那么无论调用的时候传递的是值还是指针,都是值拷贝

如果方法要求的是指针,那么无论调用的时候传递的是值还是指针,都是地址拷贝

背后的原理:go在编译的时候会根据方法定义的要求对传入的对象进行取值或取地址运算

有疑问加站长微信联系(非本文作者)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/551328.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

workbook对象需要关闭_XSSFWorkbook对象 进行zip打包时 用write资源流自动关闭处理办法...

xssfworkbook对象的write方法内会将传入的资源流自动关闭 导致下载excel失败错误代码outputstream out response.getoutputstream();zipoutputstream zos new zipoutputstream(out);xssfworkbook workbook new xssfworkbook();// 将文件写入zip内,即将文件进行打…

php for 脚本,php for循环脚本。

$dir "./$time/";$info deepScanDir($dir);for($i0; $i system("/usr/sbin/php temp.php \($i\).txt output\($i\).txt");}deepScanDir是循环文件夹下的所有文件。现在这个循环一次执行一次这个命令,我想弄一个,循环一次执行很多个…

autowired的对象为null_spring-为什么我的@Autowired对象为null?

我有下面的JSF托管bean:package com.example;import java.io.Serializable;import javax.faces.bean.ManagedBean;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;ComponentManagedBeanpublic cl…

基于mysql和php的分布式事务处理1,基于MySQL和PHP的分布式事务处理

PHP(超级文本预处理语言)是一种基于服务器端、执行效率高且易于开发的HTML内嵌式语言,是用户生成动态网页的工具之一[1].MySQL是全球最受欢迎的小型开放源码的关系型数据库管理系统,其体积小、速度快、总体拥有成本低[2].很多基于PHP技术开发的中小型网站都采用MySQL作为其后台…

ios查看线程数量_关于iOS多线程,你看我就够了(已更新)

作者:翁呀伟呀 授权本站转载。在这篇文章中,我将为你整理一下 iOS 开发中几种多线程方案,以及其使用方法和注意事项。当然也会给出几种多线程的案例,在实际使用中感受它们的区别。还有一点需要说明的是,这篇文章将会使…

php fuzzy,模糊C均值聚类算法(Fuzzy C-means)

模糊c均值聚类与k均值聚类区别k均值聚类k均值聚类的实现中,把每个样本划分到单一的类别中,亦即是每个样本只能属于一种类别,不能属于多种类别。这样的划分,称为硬划分。模糊c均值均类为了解决硬划分所带来的问题,因此有…

matlab 投票法_张量投票算法及其使用并分析.pdf

张量投票算法及其使用并分析摘 要本文主要介绍了一种新的数据分析算法,即张量投票算法.该算法完全利用图像数据,根据张量分析,矩阵论和几何的知识,对数据点进行编译和几何阐释,再根据心理学中的Gestalt原理…

dw新建php文件自动生成html,dw如何新建css规则

1、在菜单中单击“文件”选择“新建”2、在新建文档窗口,选择“空白页”—“HTML”,文档类型选择“XHTML1.0 transitional”,单击“创建”按钮3、将插入点放在文档中,然后在菜单栏单击“格式”,在弹出的下拉菜单中选择“CSS样式”…

lan口配置 petalinux_【Xilinx-Petalinux学习】-02-建立PetaLinux工程

前面我已经把PetaLinux成功安装到了Ubuntu虚拟机当中了,接下来就要实际操作,将PetaLinux移植到我们自己的硬件平台当中去。step1:硬件描述文件有两种PetaLinux工程建立的方法,一种是下载官方开发板的BSP包并安装,一种就…

oracle其他盘添加表空间吗,oracle增加表空间的四种方法

实例1:在中,磁盘空间不足是DBA都会遇到的问题,问题比较常见。--1查看表空间已经使用的百分比select a.tablespace_name,a.bytes/1024/1024 "SumMB",(a.bytes-b.bytes)/1024/1024 "used MB",b.bytes/1024/1024 "free…

oracle获取登录名,oracle如何获取当前登录的用户名

Microsoft Windows [版本 5.2.3790](C) 版权所有 1985-2003 Microsoft Corp.C:/>sqlplusSQL*Plus: Release 9.2.0.1.0 - Production on 星期三 5月 30 00:04:26 2007Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.请输入用户名: scott请输入口令:连…

广告冷启动_亚马逊新品冷启动,你的广告策略怎么定?

上新品,没有黑科技加持,纯靠PPC广告冷启动,你会怎么做?我们先来看看运作成功且销售情况稳定的ASIN的流量组成:对比这些数据,大家可以算算自己漏掉了多少流量。占了大头的关联流量中,又以“Newer…

oracle报28003,【翻译自mos文章】运行utlpwdmg.sql之后报ORA-28003, ORA-20001, ORA-20002, ORA-20003, ORA-20004 错误...

运行utlpwdmg.sql之后报ORA-28003, ORA-20001, ORA-20002, ORA-20003, ORA-20004 错误。适用于:Oracle Server - Enterprise Edition - Version 8.1.7.0 and laterInformation in this document applies to any platform.Checked for relevance on 15-Sep-2012原因&…

mysql 天数减1_mysql 日期加减天数

MySQL 为日期增加一个时间间隔:date_add()now() //now函数为获取当前时间select date_add(now(), interval 1 day); - 加1天select date_add(now(), interval 1 hour); -加1小时select date_add(now(), interval 1 minute); - 加1分钟select date_add(now(), …

oracle注入过滤了单引号,sql绕过单引号限制继续注入的解决方法

在防范sql注入时,对变量过滤不足甚至没有过滤而构造畸形SQL语句,极有可能被成功注入,比如下面这行sql,相当轻松就注入成功了:代码示例:http://www./show.asp?id1;exec master.dbo.xp_cmdshell net user angel pass /a…

python实现英文新闻摘要自动提取_Automotive Innovation摘要集系列2:Intelligent and Connected Vehicles...

为便于广大科技工作者更好的了解中国汽车行业首个英文学术期刊《Automotive Innovation》,并更快的定位到自己感兴趣的论文,编辑部把2018-2019年刊出的70篇论文摘要进行集结,并按照节能与环保(Energy-saving & Eco-systems)、智能网联汽车…

oracle data guard闪回,11gR2 Active Data Guard 闪回 - flashback database / snapshot standby - 2

二,11g 使用snapshot方式设置Data Guard闪回snapshot standby是11g引入的新特性,它不需要开启flashback database特性,就可以让physical standby数据库以read-write模式开启,而后可以退回到standby模式,所有open模式下…

fp算法例题_机器学习(九)—FP-growth算法

本来老师是想让我学Hadoop的,也装了Ubuntu,配置了Hadoop,一时间却不知从何学起,加之自己还是想先看点自己喜欢的算法,学习Hadoop也就暂且搁置了,不过还是想问一下园子里的朋友有什么学习Hadoop好点的资料&a…

linux 改变文件夹属性,技术|在Linux中用chattr和lsattr命令管理文件和目录属性

为了允许添加数据,防止更改或者删除等,文件和文件夹可以设定了特定的控制属性。例如,你可以在关键的系统文件或者文件夹中启用属性,然后没有任何用户,包括root,可以删除或者修改它,比如不允许使…

封头名义厚度如何圆整_松原封头价格

松原封头价格这种情况下我们常常是选用宽度1500毫米的板材开展下料。同时为了保证其的宽度,借此需要下两块料。此外在下料前需要在原板材上面选择一段试样,需对试样实施物理性能测试和化学元素含量的测试,缘于物理性能决定封头的减薄率&#…