go语言中的函数详解
1. 引言
函数是编程中不可或缺的组成部分,无论是在Go
语言还是其他编程语言中,函数都扮演着重要的角色。函数能够将一系列的操作封装在一起,使得代码更加模块化、可重用和易于维护。
在本文中,我们将详细介绍Go语言中函数的概念和使用方法,包括函数的定义、参数和返回值、调用方式、可变参数、函数作为参数和返回值等方面的内容。
2. 函数的基本定义
在Go语言中,定义函数需要按照以下语法:
func functionName(parameter1 type1, parameter2 type2) returnType {// 函数体// 可以包含一系列的语句和操作return value // 返回值(如果有)
}
其中,各个部分的含义如下:
func
: 关键字用于定义函数。functionName
: 函数名,用于唯一标识该函数。parameter1, parameter2
: 参数列表,函数可以接收零个或多个参数。每个参数由参数名和参数类型组成,多个参数之间使用逗号分隔。type1, type2
: 参数的类型,指定参数的数据类型。returnType
: 返回类型,指定函数的返回值的数据类型。如果函数没有返回值,则返回类型为空。return value
: 可选项,用于返回函数的结果。如果函数定义了返回类型,则需要使用return
语句将结果返回给调用者。
下面是一个示例函数的定义:
func add(a int, b int) int {sum := a + breturn sum
}
上述示例中,函数名为add
,接收两个参数a
和b
,类型为int
,并且返回类型也为int
。函数体内部计算参数的和,并将结果使用return
语句返回。
3.1 值传递
传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
默认情况下,Go 语言使用的是值传递,即在调用过程中不会影响到实际参数。
以下定义了 swap() 函数:
package mainimport "fmt"func main() {/* 定义局部变量 */var a int = 100var b int = 200fmt.Printf("交换前 a 的值为 : %d\n", a)fmt.Printf("交换前 b 的值为 : %d\n", b)/* 通过调用函数来交换值 */swap(a, b)fmt.Printf("交换后 a 的值 : %d\n", a)fmt.Printf("交换后 b 的值 : %d\n", b)
}/* 定义相互交换值的函数 */
func swap(x, y int) int {var temp inttemp = x /* 保存 x 的值 */x = y /* 将 y 值赋给 x */y = temp /* 将 temp 值赋给 y*/return temp
}
运行结果:
交换前 a 的值为 : 100
交换前 b 的值为 : 200
交换后 a 的值 : 100
交换后 b 的值 : 200
可见交换前后a,b的值没变。
所以值传递不会改变所传入实参的值。只是复制一份值用于函数体执行而已。
3.2 引用参数
引用参数是通过将参数的地址传递给函数来进行传递的。这样函数就可以通过指针来间接地修改原始数据。因为传递指针只需要占用较小的内存,所以其通常适用于需要修改原始数据或者数据量较大的场景。下面通过一个切片的例子来进行说明,切片内部保存了数组的指针,可以认为是传递了数组引用:
func appendValue(slice []int, value int) {slice = append(slice, value)fmt.Println("Inside appendValue function:", slice)
}func main() {numbers := []int{1, 2, 3}appendValue(numbers, 4)fmt.Println("After function call:", numbers)
}
输出结果为:
Inside appendValue function: [1 2 3 4]
After function call: [1 2 3 4]
在上述示例中,appendValue
函数接收一个切片作为引用参数slice
,并在函数内部使用append
函数向切片中追加一个值。这个修改会影响到原始的numbers
切片。
所以如果函数内想要修改参数值,此时可以通过传递引用参数来达到这个目的。
(2)引用传递
引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
引用传递将指针参数传递到函数内,以下是交换函数 swap() 使用了引用传递:
package mainimport "fmt"func main() {var a int = 100var b int = 200fmt.Printf("交换前a的值为:%d\n", a)fmt.Printf("交换前b的值为:%d\n", b)/* 调用 swap() 函数* &a 指向 a 指针,a 变量的地址* &b 指向 b 指针,b 变量的地址*/swap(&a, &b)fmt.Printf("交换后,a 的值 : %d\n", a)fmt.Printf("交换后,b 的值 : %d\n", b)
}func swap(x, y *int) int {var temp inttemp = *x /* 保存 x 的值 */*x = *y /* 将 y 值赋给 x */*y = temp /* 将 temp 值赋给 y*/return temp
}
输出结果:
交换前,a 的值 : 100
交换前,b 的值 : 200
交换后,a 的值 : 200
交换后,b 的值 : 100
注意:
- 无论是值传递,还是引用传递,传递给函数的都是变量的副本,不过,值传递是值的拷贝。引用传递是地址的拷贝,一般来说,地址拷贝更为高效。而值拷贝取决于拷贝的对象大小,对象越大,则性能越低。
- map、slice、chan、指针、interface默认以引用的方式传递。
3.3 可变参数
Go
语言支持可变参数函数,即函数可以接受可变数量的参数。在Go
语言中,可变参数函数使用 ...
操作符来表示。该操作符放置在参数类型前面,用于指示该参数可以接受多个值。具体语法如下:
func myfunc(args ...int) { //0个或多个参数
}func add(a int, args…int) int { //1个或多个参数
}func add(a int, b int, args…int) int { //2个或多个参数
}
其中,param
是可变参数的名称,Type
是可变参数的类型。在函数体内,我们可以像处理切片一样处理可变参数,使用循环或索引来遍历和访问参数的值。下面是一个使用可变参数函数的示例:
func sum(numbers ...int) int {total := 0for _, num := range numbers {total += num}return total
}func main() {result := sum(1, 2, 3, 4, 5)fmt.Println("Sum:", result)
}
在上述示例中,
sum
函数使用可变参数numbers
来接收多个整数值。在函数体内,我们使用循环遍历numbers
切片,并累加每个整数值到total
变量中。最后,函数返回累加的总和。
实例 2:使用切片赋值
在参数赋值时可以不用一个一个的赋值,可以直接传递一个数组或者切片,特别注意的是在参数后加上“…
”即可。
使用 slice 对象做变参时,必须展开。(slice…)
import ("fmt"
)func test(s string, n ...int) string {var x intfor _, i := range n {x += i}return fmt.Sprintf(s, x)
}func main() {s :=[] int{1,2,3}res :=test("sum: %d",s...)println(res)
}
4、函数返回值
-
返回值的忽略
_
标识符,用来忽略函数的某个返回值。
Golang返回值不能用容器对象接收多返回值。只能用多个变量,或 “_” 忽略。 -
多返回值可直接作为其他函数调用实参。
package mainfunc test() (int, int) {return 1, 2
}
func add(x, y int) int {return x + y
}
func sum(n ...int) int {var x intfor _, i := range n {x += i}return x
}func main() {println(add(test()))println(sum(test()))
}
运行结果:
3
3
3.命名返回值
Go 函数的返回值可以被命名,就像在函数体开头声明变量。
返回值的名称应当具有一定的意义,可以作为文档使用。
命名返回参数可看做与形参类似的局部变量,最后由 return 隐式返回。
package mainfunc add(x, y int) (z int) {{ // 不能在一个级别,引发 "z redeclared in this block" 错误。z = x + y// return // Error: z is shadowed during returnreturn // 必须显式返回。}
}
func main() {println(add(1, 2))
}
注意:命名返回参数可被同名局部变量遮蔽,此时需要显式返回。
package mainfunc add(x, y int) (z int) {{ // 不能在一个级别,引发 "z redeclared in this block" 错误。z = x + y// return // Error: z is shadowed during returnreturn z // 必须显式返回。}
}
func main() {println(add(1, 2))
}
4.没有参数的 return 语句返回各个返回变量的当前值。这种用法被称作“裸”返回。
直接返回语句仅应当用在像下面这样的短函数中。在长的函数中它们会影响代码的可读性。
package mainimport "fmt"func add(a, b int) (c int) {c = a + breturn
}func calc(a, b int) (sum int, avg int) {sum = a + bavg = (a + b) / 2return
}
func main() {var a, b int = 1, 2c := add(a, b)sum, avg := calc(a, b)fmt.Println(c, sum, avg)
}
运行结果:
3 3 1
在 Go 语言中,函数是一等公民,这意味着函数可以作为参数传递给其他函数,也可以作为返回值返回。以下是一些函数作为实参的例子:
实例1:传递函数作为参数
package mainimport "fmt"// 定义一个函数,它来接受一个函数作为参数
func applyFunction(x int, y func(int) int) int {return y(x)
}// 定义一个简单的函数,用于增加
func addFive(x int) int {return x + 5
}
func main() {result := applyFunction((10), addFive)fmt.Println(result)//输出:15
}
实例2:使用匿名函数
在 Go 语言中,匿名函数(也称为立即执行函数或 lambda 表达式)是一种没有名称的函数,通常用于需要函数作为参数的场合。匿名函数可以在定义它们的代码块内立即使用,也可以作为参数传递给其他函数。
package mainimport "fmt"
//applyFunction接受一个函数作为参数,并使用这个函数处理输入值
func applyFunction(x int, f func(int) int) int {return f(x)
}
func main() {//定义并传递一个匿名函数result := applyFunction(10, func(x int) int {return x * 2})fmt.Println(result)//输出:20
}
相关文章:
go语言中的函数详解
1. 引言 函数是编程中不可或缺的组成部分,无论是在Go语言还是其他编程语言中,函数都扮演着重要的角色。函数能够将一系列的操作封装在一起,使得代码更加模块化、可重用和易于维护。 在本文中,我们将详细介绍Go语言中函数的概念和…...

ubuntu18.04运行OpenPCDet出现的问题
一、概述 在编译成功OpenPCDet的源代码之后,发现在运行demo时候,依旧出现了很多问题,在此对出现的问题进行总结记录。 二、问题分析 (一)ModuleNotFoundError:No module named av2 如图所示 这个问题比较简单&#x…...

【C++】——继承(下)
【C】——继承(下) 5 继承与友元6 继承与静态成员7 多继承7.1 继承模型7.2 菱形继承的问题7.3 虚继承7.4 多继承中的指针偏移问题 8 组合与继承 5 继承与友元 友元关系不能被继承。即一个函数是父类的友元函数,但不是子类的友元函数。也就是说…...

Pandas处理时间序列之光谱分析与聚类
import matplotlib.pylab as plt %matplotlib inline import numpy as np from numpy import fft import pandas as pd 一、光谱分析 • 将时间序列分解为许多正弦或余弦函数的总和 • 这些函数的系数应该具有不相关的值 • 对正弦函数进行回归 光谱分析应用场景 基于光谱的…...
【WebGIS】Cesium:GeoJSON加载
GeoJSON 是一种常用的地理空间数据格式,它用于表示简单的地理要素及其属性,并且被广泛应用于 Web 地图和 GIS 系统中。在 Cesium 中,GeoJSON 文件可以很方便地加载到三维场景中展示,并且可以添加样式和事件处理。本文将为你提供详…...

PageHelper实现分页查询
前端发送的请求参数 后端返回的对象类型 Controller类实现 /*** 员工分页查询* param employeePageQueryDTO* return*/GetMapping("/page")ApiOperation("员工分页查询")public Result<PageResult> page(EmployeePageQueryDTO employeePageQueryDTO)…...

边缘检测评估方法:FOM、RMSE、PSNR和SSIM对比实验和理论研究
图像分割与边缘检测是密切相关的计算机视觉任务。以下图1展示了一个海岸线分割模型的输出示例: 图1: 分割掩码到边缘图的转换过程(数据集:LICS) 模型将每个像素分类为陆地或海洋(分割掩码)。随后,海岸线被定义为分类发生变化的像素位置(边缘图)。边缘检测可以通过提取图像分割…...
MySql 多表查询
多表查询:指从多张表中查询数据。 笛卡儿积:笛卡儿积是指在数学中,两个集合(A集合 和 B集合)的所有组合情况。 连接查询 内连接:相当于查询A、B交集部分数据外连接 左外连接:查询左表所有数据…...

数学建模算法与应用 第11章 偏最小二乘回归及其方法
目录 11.1 偏最小二乘回归概述 11.2 Matlab 偏最小二乘回归命令 Matlab代码示例:偏最小二乘回归 11.3 案例分析:化学反应中的偏最小二乘回归 Matlab代码示例:光谱数据的PLS回归 习题 11 总结 偏最小二乘回归(Partial Least …...

【MATLAB代码】TDOA定位,4个基站、3个时间差、三维定位(可直接复制粘贴到MATLAB上运行)
文章目录 程序结构源代码运行结果代码结构输入输出解析该MATLAB代码实现了基于时间差定位(TDOA, Time Difference of Arrival)的方法,使用最小二乘法在三维空间中估计一个未知点的位置。该算法利用一个主锚点和三个副锚点的已知位置,通过计算信号传播时间差来推算出目标位置…...

uniapp引入ThorUI的方法
1、下载文件 2、复制相应的文件除了pages 3、往项目中复制即可 4、引入即可实现 5、添加easycome自动引入...
面试官:手写一个New
在JavaScript中,new操作符主要用于创建一个对象示例。通过new操作符,可以创建一个新的对象,并将这个对象的原型链只想一个构造函数的原型对象,然后执行构造函数中的代码初始化这个新对象。 常见的new的使用为 new Array() new Set…...

merlion的dashboard打开方法
安装好merlion包后,在anaconda prompt中进行如下图操作: 先进入创建好的虚拟环境:conda activate merlion再执行命令:python -m merlion.dashboard在浏览器中手动打开图中的地址: http://127.0.0.1:8050 打开后的界面…...

自监督学习:引领机器学习的新革命
引言 自监督学习(Self-Supervised Learning)近年来在机器学习领域取得了显著进展,成为人工智能研究的热门话题。不同于传统的监督学习和无监督学习,自监督学习通过利用未标注数据生成标签,从而大幅降低对人工标注数据…...

Web安全常用工具 (持续更新)
前言 本文虽然是讲web相关工具,但在在安全领域,没有人是先精通工具,再上手做事的。鉴于web领域繁杂戎多的知识点(工具是学不完的,哭),如果你在本文的学习过程中遇到没有学过的知识点࿰…...

不踩坑,青龙面板小问题解决方案~
好久没写了,随手记录一下。 1. 新建目录 很多人跟我一样入坑的手机免root青龙面板,一般用的都是2.10.13版本。这个版本比较早,似乎没有新建目录的功能(也可能是我不会用哈哈),以下是对比图: 大家…...

2025秋招倒计时---招联金融
【投递方式】 直接扫下方二维码,或点击内推官网https://wecruit.hotjob.cn/SU61025e262f9d247b98e0a2c2/mc/position/campus,使用内推码 igcefb 投递) 【招聘岗位】 后台开发 前端开发 数据开发 数据运营 算法开发 技术运维 软件测试 产品策…...

基于yolov8、yolov5的果蔬检测系统(含UI界面、数据集、训练好的模型、Python代码)
项目介绍 项目中所用到的算法模型和数据集等信息如下: 算法模型: yolov8、yolov8 SE注意力机制 或 yolov5、yolov5 SE注意力机制 , 直接提供最少两个训练好的模型。模型十分重要,因为有些同学的电脑没有 GPU࿰…...

出海快报 | “三消+短剧”手游横空出世,黄油相机“出圈”日本市场,从Q1看日本手游市场趋势和机会
编者按:TopOn出海快报栏目为互联网出海从业者梳理出海热点,供大家了解行业最新发展态势。 1.“三消短剧”横空出世,融合创新手游表现亮眼 随着竞争的加剧,新产品想要突出重围,只能在游戏中加入额外的元素。第一次打开…...

Linux高效查日志命令介绍
说明:之前介绍Linux补充命令时,有介绍使用tail、grep命令查日志; Linux命令补充 今天发现仅凭这两条命令不够,本文扩展介绍一下。 命令一:查看日志开头 head -n 行数 日志路径如下,可以查看程序启动是否…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...

【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...

从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...

centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...

【Linux】Linux 系统默认的目录及作用说明
博主介绍:✌全网粉丝23W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...