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



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

    值传递和引用传递

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

    由于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)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

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

    swap前的x,y: hello world
    swapValue后的x,y: hello world
    swapRef后的x,y: world hello

    闭包

    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))
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

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

    >go run func.go
    0
    1
    3
    6
    10
    12
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    柯里化

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

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

    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)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    运行结果为

    AddMinus(2,5,Add) = 7
    
    • 1

    defer

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

    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
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

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

  • 相关阅读:
    智能合约通过getAmountsOut方法获取最近币对价格
    视频化全链路智能上云?一文详解什么是阿里云视频云「智能媒体生产」
    项目-五子棋双人对战:游戏房间的管理(5)
    单链表—C语言实现数据结构
    隐式类型转换(整形提升)
    ADS版图中连接提示线设置
    Python Canvas and Grid Tkinter美妙布局canvas和其他组件
    SpringBoot的 8 个优点
    php实战案例记录(15)获取GET和POST请求参数
    【无标题】
  • 原文地址:https://blog.csdn.net/m0_37816922/article/details/133377970