【Go语言】Go语言中的函数

Go语言中的函数

Go语言中,函数主要有三种类型:

  • 普通函数

  • 匿名函数(闭包)

  • 类方法

1 函数定义

Go语言函数的基本组成包括:关键字func、函数名、参数列表、返回值、函数体和返回语句。Go语言是强类型语言,无论是参数还是返回值,在定义函数时,都需要声明其类型。

如下是Go语言中函数的一个简单示例:

// 参数类型 int
// 返回类型 int
func add(a, b int) int  {return a + b
}

2 函数调用

2.1 调用同一个包定义的函数

如果函数在同一个包中,只需要直接调用即可:

func add(a, b int) int  {return a + b
}func main()  {fmt.Println(add(1, 2))  // 3
}

2.2 调用其他包定义的函数

如果函数是在不同的包中,需要先导入该函数所在的包,然后才能调用该函数,例如 Add 函数在 calculator 包中。

package calculatorfunc Add(a, b int) int  {return a + b
}

在 main 包中调用Add函数。

package mainimport ("fmt""calculator"
)
func main()  {fmt.Println(calculator.Add(1, 2))   // 3
}

注意:在调用其他包定义的函数时,只有这个函数名首字母大写的才可以被调用,例如函数名为add就会出现如下情况:

2.3 系统内置函数

Go语言中内置了常用的函数,如下所示

名称说明
close用于在管道通信中关闭一个管道
lencaplen 用于返回某个类型的长度(字符串、数组、切片、字典和管道),cap 则是容量的意思,用于返回某个类型的最大容量(只能用于数组、切片和管道)
newmakenewmake 均用于分配内存,new 用于值类型和用户自定义的类型(类),make 用于内置引用类型(切片、字典和管道)。它们在使用时将类型作为参数:new(type)make(type)new(T) 分配类型 T 的零值并返回其地址,也就是指向类型 T 的指针,可以用于基本类型:v := new(int)make(T) 返回类型 T 的初始化之后的值,所以 make 不仅分配内存地址还会初始化对应类型。
copyappend分别用于切片的复制和动态添加元素
panicrecover两者均用于错误处理机制
printprintln打印函数,在实际开发中建议使用 fmt 包
complexrealimag用于复数类型的创建和操作

3 参数传递

3.1 按值传参

Go语言默认使用按值传参来传递参数,也就是传递参数值的一个副本,函数收到传递进来的参数后,会将参数值拷贝给声明该参数的变量(也叫做形式参数,简称形参),如果在函数体中有对参数值做修改,实际上修改的是形参值,这不会影响到实际传递进来的参数值(也叫实际参数,简称实参)。

示例代码如下:

// a,b 是形式参数
func add(a, b int) int  {a *= 2b *= 3return a + b
}
func main()  {x, y := 1, 2// x,y 是实际参数z := add(x, y)// z的值是x*2+y*3=8,但x,y的值并未改变fmt.Printf("add(%d, %d) = %d\n", x, y, z)  
}

3.2 引用传参

如果需要实现在函数中修改形参值的同时改变实参,需要引用传参来实现,此时传递给函数的参数是一个指针,而指针代表的是实参的内存地址,修改指针引用的值即修改变量内存地址中存储的值,因此实参的值也会被修改。

示例代码如下:

// a,b 是形式参数
func add(a, b *int) int  {*a *= 2*b *= 3return *a + *b
}
func main()  {x, y := 1, 2// x,y 是实际参数z := add(&x, &y)// z的值是x*2+y*3=8,由于我们直接修改了内存超出地址的值,因此x变为2,y变为6fmt.Printf("add(%d, %d) = %d\n", x, y, z)  
}

在函数调用时,像切片(slice)、字典(map)、接口(interface)、通道(channel)这样的引用类型默认使用引用传参。

4 变长参数

变长参数指的是函数参数的数量不确定,可以按照需要传递任意数量的参数到函数。

4.1 基本定义和传值

只需要在参数类型前加上 ... 前缀,就可以将该参数声明为变长参数。

// 函数Myfunc()接受任意数量的参数,这些参数的类型全部是int
func Myfunc(numbers ...int){for _,number := range numbers {fmt.Println(number)}
}
// 函数可以按照如下方式调用:
Myfunc(1,2,3,4,5,6)
Myfunc(1,2,3)

函数调用测试:

变长参数还支持传递一个 []int 类型的切片,传递切片时需要在末尾加上 ... 作为标识,标识对应的参数类型是变长参数:

slice := []int{1,2,3,4,5,6}
Myfunc(slice...)
Myfunc(slice[1:3]...)

注:...type 只能作为函数的参数类型存在,并且必须是函数的最后一个参数。

4.2 任意类型的变长参数(泛型)

Go语言中,可以通过指定变长参数类型为 interface{} 来实现参数的任意类型传递。

代码实现如下:

// 变长参数,可以传递任意个数的参数,类型无要求
func Myfunc2(params ...interface{}) {for _, param := range params {fmt.Println(param)}
}

5 多返回值

5.1 多返回值

Go语言中,函数能够支持多返回值,经常用在程序出错的时候。

代码示例如下:

// 函数定义
func AddFunc(a, b *int) (int, error) {if *a < 0 || *b < 0 {err := errors.New("仅支持非负整数的相加")return 0, err}return *a + *b, nil
}
// 函数调用
x, y := -1, 2
z, err := function.AddFunc(&x, &y)
if err != nil {fmt.Println(err.Error())return
}
fmt.Printf("%d + %d = %d", x, y, z)

5.2命名返回值

函数设置多返回值时,还可以对返回值进行变量命名,这样就可以直接在函数中对返回值变量进行赋值,而不需要按照指定的返回值格式返回多个变量。

代码示例:

// 函数定义
func AddFunc2(a, b *int) (c int, err error) {if *a < 0 || *b < 0 {err = errors.New("仅支持非负整数的相加")return}c = *a + *breturn
}
// 函数调用
x, y := -1, 2
z, err := function.AddFunc2(&x, &y)
if err != nil {fmt.Println(err.Error())return
}
fmt.Printf("%d + %d = %d", x, y, z)

6 匿名函数与闭包

6.1 匿名函数的定义和使用

匿名函数是一种没有指定函数名的函数声明方式。

代码示例如下:

func(a,b int) int {return a+b
}

Go语言中,匿名函数也可以赋值给一个变量或者直接执行:

// 将匿名函数赋值给变量
sum := func(a,b int) int {return a+b
}
// 调用匿名函数 add
fmt.Print(sum(1,2))// 也可以在定义的时候,直接调用匿名函数
func(a,b int){fmt.Println(a+b)
} (1,2)

6.2 匿名函数与闭包

闭包:指引用了外部函数作用域中的变量的函数。也即,闭包是一个函数及其相关引用环境的组合。

匿名函数和闭包的关系:匿名函数可以用来创建闭包,当一个匿名函数引用了外部函数作用域中的变量时,该匿名函数就成了一个闭包。

6.3 匿名函数的使用场景

6.3.1 保证局部变量的安全性

匿名函数内部声明的局部变量无法从外部修改,从而确保了安全性(类似类的私有属性)。

代码示例如下:

var j int =1
f := func(){var i int = 1fmt.Println(i,j)
}
f()
j += 2
f()

如上代码运行所示,匿名函数引用了外部变量j,所以同时也是个闭包,变量f指向的闭包引用了局部变量i和j,i在闭包内定义,其值被隔离,不能从外部修改变量,j在闭包外定义,所以可以从外部修改,闭包只是引用了变量j的值。

6.3.2 将匿名函数作为函数参数

匿名函数除了可以赋值给普通变量外,还可以作为函数参数传递到函数中进行调用,就像普通数据类型一样。

代码示例:

add := func(a, b int) int {return a + b
}
func(call func(int, int) int) {fmt.Println(call(1, 2))
}(add)

6.3.3 将匿名函数作为函数返回值

Go语言中,匿名函数也能够作为返回值使用。

代码示例:

func defaultAdd(a, b int) func() int {return func() int {return a + b}
}// 此时返回的是匿名函数
addFunc := defaultAdd(1, 2)
// 这里才会真正的执行加法操作
fmt.Println(addFunc())

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

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

相关文章

【MySQL | 第五篇】MySQL事务总结

文章目录 5.MySQL事务5.1什么是事务&#xff1f;5.2什么是数据库事务&#xff1f;5.3数据库事务四大特性5.4并发事务带来的问题及解决方案&#xff1f;5.4.1脏读/不可重复读/幻读5.4.2不可重复读和幻读有什么区别&#xff1f;5.4.3解决并发事务带来的问题&#xff08;1&#xf…

springboot实战笔记

springboot实战笔记 用户模块开发用户登录接口实现根据token获取用户信息检查账号是否可用用户注册接口实现 首页模块开发查询首页分类分页查询首页头条信息查询头条详情 头条模块开发登陆检查头条发布和登录保护拦截器头条根据id回显头条修改头条删除 用户模块开发 用户登录接…

springboot/ssm医院病历管理系统Java医院住院病历信息管理系统web

springboot/ssm医院病历管理系统Java医院住院病历信息管理系统web 基于springboot(可改ssm)vue项目 开发语言&#xff1a;Java 框架&#xff1a;springboot/可改ssm vue JDK版本&#xff1a;JDK1.8&#xff08;或11&#xff09; 服务器&#xff1a;tomcat 数据库&#xf…

聚观早报 | 阅文去年净利增三成;iQOO Z9系列官宣

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 3月20日消息 阅文去年净利增三成 iQOO Z9系列官宣 英伟达发布全新构架 一加Ace 3V设计细节 小米Civi 4 Pro核心…

章鱼网络 Community Call #19|​开启与 Eigenlayer 的合作

香港时间2024年3月8日12点&#xff0c;章鱼网络举行第19期 Community Call。 在过去的一个月&#xff0c;章鱼网络在成功完成 $NEAR Restaking 功能的安全审计之后&#xff0c;一直在稳步吸引关注。事实上&#xff0c;在整个行业中&#xff0c;我们是极少数已经推出 Restaking …

富格林:揭露黑幕套路安全规避风险

富格林悉知&#xff0c;作为黄金市场的交易者&#xff0c;掌握规避黑幕套路的正规手段的重要性不言而喻。如果投资者能够定制安全防范策略抵制黑幕并做到远离&#xff0c;就能够规避被骗风险。想要安全做单增加收益&#xff0c;投资者需要尊重市场&#xff0c;提高安全意识&…

八大元素,让你的网站科技感拉满,极易落地执行。

Hello&#xff0c;我是大千UI工场&#xff0c;这篇分享各类网页UI的设计风格&#xff0c;就从大家最喜欢的科技感开始吧&#xff0c;欢迎友友们持续关注&#xff0c;我将持续更新&#xff0c;如有设计需求&#xff0c;可以私信我。 在网页UI中&#xff0c;科技感是指通过设计元…

【使用xlrd、xlutils读写excel】

使用xlrd、xlutils读写excel 1、环境和版本2、相关使用方法封装2.1 根据行下标返回对应行数据2.2 根据列下标返回对应列数据2.3 读取指定单元格数据2.4 通过表单名读取全部数据2.5 通过表索引读取全部数据2.6 向已存在sheet中追加数据2.7 原文件基础上新建的sheet并写入数据 3、…

数据结构奇妙旅程之冒泡排序

冒泡排序&#xff08;Bubble Sort&#xff09;是一种简单的排序算法。它重复地遍历要排序的数列&#xff0c;一次比较两个元素&#xff0c;如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换&#xff0c;也就是说该数列已经排序完成。 这个算…

医学YOLOv8 | 脑肿瘤检测实战

在医疗保健领域&#xff0c;准确和高效地识别脑肿瘤是一个重大挑战。本文中&#xff0c;我们将探讨一种使用 YOLOv8&#xff0c;一种先进的目标检测模型&#xff0c;将脑肿瘤进行分类的新方法&#xff0c;其准确率达到了 99%。通过将深度学习与医学图像相结合&#xff0c;我们希…

代码随想录阅读笔记-字符串【翻转字符串中单词】

题目 给定一个字符串&#xff0c;逐个翻转字符串中的每个单词。 示例 1&#xff1a; 输入: "the sky is blue" 输出: "blue is sky the" 示例 2&#xff1a; 输入: " hello world! " 输出: "world! hello" 解释: 输入字符串可以在前…

阿里云ECS服务器安装java环境相关软件

当前服务器版本为&#xff1a;Alibaba Cloud Linux 3.2104 LTS 64位 # lsb_release -a LSB Version: :core-4.1-amd64:core-4.1-noarch Distributor ID: AlibabaCloud Description: Alibaba Cloud Linux release 3 (Soaring Falcon) Release: 3 Codename: SoaringFalcon# cat…

数据库简答题:期末+复试

文章目录 1.事务的特性:2.并发操作带来的数据不一致:4.区别几种范式:5.数据、数据库、数据库管理系统、数据库系统6.关系、关系模式和关系数据库的区别:7.关系数据库的特点:8.数据模型包括什么:9.逻辑独立性、物理独立性:10.人工管理阶段和数据库系统和文件系统的区别:11.等值连…

【Android】【Bluetooth Stack】蓝牙电话本协议分析(超详细)

1. 精讲蓝牙协议栈&#xff08;Bluetooth Stack&#xff09;&#xff1a;SPP/A2DP/AVRCP/HFP/PBAP/IAP2/HID/MAP/OPP/PAN/GATTC/GATTS/HOGP等协议理论 2. 欢迎大家关注和订阅&#xff0c;【蓝牙协议栈】专栏会持续更新中.....敬请期待&#xff01; 目录 1. 协议简述 1.1 PBAP…

个人商城系统开源(配置支付宝支付2)

原文地址&#xff1a;个人商城系统开源&#xff08;配置支付宝支付2&#xff09; - Pleasure的博客 下面是正文内容&#xff1a; 前言 在上一篇文章中我曾提到过关于网站支付宝支付的方法&#xff0c;接下来我们来介绍第二种。 个人博客地址&#xff1a;个人商城系统开源&…

GPT模型支持下的Python-GEE遥感云大数据分析、管理与可视化技术及多领域案例应用

随着航空、航天、近地空间等多个遥感平台的不断发展&#xff0c;近年来遥感技术突飞猛进。由此&#xff0c;遥感数据的空间、时间、光谱分辨率不断提高&#xff0c;数据量也大幅增长&#xff0c;使其越来越具有大数据特征。对于相关研究而言&#xff0c;遥感大数据的出现为其提…

FPGA高端项目:FPGA基于GS2971+GS2972架构的SDI视频收发+GTX 8b/10b编解码SFP光口传输,提供2套工程源码和技术支持

目录 1、前言免责声明 2、相关方案推荐本博主所有FPGA工程项目-->汇总目录本博已有的 SDI 编解码方案本方案的SDI接收发送本方案的SDI接收图像缩放应用本方案的SDI接收纯verilog图像缩放纯verilog多路视频拼接应用本方案的SDI接收HLS图像缩放HLS多路视频拼接应用本方案的SDI…

C++:类和对象(上篇)

目录&#xff1a; 一&#xff1a;面向对象和过程的介绍 二&#xff1a;类的引入 三&#xff1a;类的定义 四&#xff1a;类的访问限定符以及封装 五&#xff1a;类的作用域 六&#xff1a;类的实例化 七&#xff1a;类对象大小的计算 八&#xff1a;类成员函数的this指…

【Linux】编译器-gcc/g++的使用(预处理、编译、汇编、连接)

目录 01.预处理&#xff08;宏替换&#xff09; 02.编译&#xff08;生成汇编&#xff09; 03.汇编&#xff08;生成机器可识别码&#xff09; 04.连接&#xff08;生成可执行文件或库文件&#xff09; 05.选项 编译器在编译代码时包含以下四个步骤&#xff1a;1.预处理 2…

商品规格存储问题

准备条件 <dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version> <!-- 指定您需要的 FastJSON 版本 --></dependency>Testvoid test6() {// 创建 JSON 对象JSONObjec…