Go语言函数进阶:值传递、引用传递、函数式编程

文章目录

go语言教程: 安装入门➡️ for循环➡️ 数组、切片和指针➡️ switch和map

值传递和引用传递

go语言中,函数通过关键字func定义,对于传入和返回的参数需要做类型的定义,其返回值可以不唯一。

由于Go支持指针,当输入变量为指针的时候,函数将直接改变指针所指的数据,这种情况叫做引用传递。而值传递则不会改变函数外的任何变量。

下面分别用值传递和引用传递这两种方式,来交换两个变量的值,

go 复制代码
//func.go
package main
import "fmt"

// 若a和b的数据类型一致,可统一标注数据类型
func swapValue(a,b string)(string,string){
	var temp string
	temp = a
	a = b
	b = temp
	return a, b
}

func swapRef(a,b *string){
	var temp string
	temp = *a
	*a = *b
	*b = temp
}

func main(){
	x := "hello"
	y := "world"

	fmt.Println("swap前的x,y:",x, y)
	swapValue(x,y)
	fmt.Println("swapValue后的x,y:", x, y)
	swapRef(&x,&y)
	fmt.Println("swapRef后的x,y:", x, y)
}

其中,swapValue是值传递函数,将传入的两个字符串,交换位置后以元组的形式返回;swapRef为引用传递,将直接改变指针所指对象。其运行结果为

swap前的x,y: hello world

swapValue后的x,y: hello world

swapRef后的x,y: world hello

闭包

go语言虽非纯种的函数式语言,但也支持一些类似闭包和匿名函数等操作,而且函数理所当然地可以被作为参数在其他函数中传入传出。

所谓闭包,即附有数据的函数。一般来说,一个函数一经定义,内部参数变不可更替;而闭包中的自由变量则是可以更改的。

go 复制代码
func record() func(v int) int{
	sum:=0		
	return func(v int) int{
		sum += v
		return sum//这个函数的返回值是sum
	}
}
func main(){
	test := record()
	for index := 0; index < 5; index++ {
		fmt.Println(test(index))
	}
	fmt.Println(test(2))
}

上例中,record的返回值是一个匿名函数,而其中的sum作为一个自由变量,会随着函数的运行而发生变化。其运行结果如下,随着函数的不断运行,record中的sum也随之而不断变化。

go 复制代码
>go run func.go
0
1
3
6
10
12

柯里化

函数既然可以作为参数,就能够起到非常优雅的回调效果,同时可以很便利地进行柯里化。所谓柯里化,即把多个输入参数的函数变成一个输入参数的函数。

下例中,通过type关键字,创建了一个数据类型Callback,这个类型的实质是一个输入两个整型返回一个整型的函数。从而Add和Minus都是复合Callback的函数。最后在主函数中,就调用了二者。

go 复制代码
func Add(a,b int) int{
	return a+b
}

func Minus(a,b int) int{
	return a-b
}

type CallBack func(x,y int)int

func AddMinus(a,b int, call CallBack) int{
	return call(a,b)	//即call(a,b)
}
func main(){
	fmt.Println("AddMinus(2,5,Add) = "AddMinus(2,5,Add))	//即Add(2,5)
}

运行结果为

AddMinus(2,5,Add) = 7

defer

go语言中还提供了一个不明觉厉的工具,通过defer可以在一个方法返回之前定义一些功能,可以理解为通过defer强化了关键字return,为其添加了一些功能。

go 复制代码
func deferTest(){
	defer func(){fmt.Println("1")}()
	defer func(){fmt.Println("2")}()
	defer func(){fmt.Println("3")}()

	fmt.Println("4")		//函数主体
}
func main(){
	deferTest()	//输出为4,3,2,1
	}

通过上面这个例子可以看到,defer的调用顺序是先进后出的。

相关推荐
Ajiang28247353042 小时前
对于C++中stack和queue的认识以及priority_queue的模拟实现
开发语言·c++
幽兰的天空2 小时前
Python 中的模式匹配:深入了解 match 语句
开发语言·python
Theodore_10225 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
----云烟----7 小时前
QT中QString类的各种使用
开发语言·qt
lsx2024067 小时前
SQL SELECT 语句:基础与进阶应用
开发语言
开心工作室_kaic7 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
向宇it7 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎
武子康7 小时前
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据仓库·sql·mybatis·springboot·springcloud
qq_17448285758 小时前
springboot基于微信小程序的旧衣回收系统的设计与实现
spring boot·后端·微信小程序
转世成为计算机大神8 小时前
易考八股文之Java中的设计模式?
java·开发语言·设计模式