一文熟悉 Go 函数
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一文熟悉 Go 函数相关的知识,希望对你有一定的参考价值。
耐心和持久胜过激烈和狂热。
哈喽大家好,我是陈明勇,今天分享的知识是 Go 的函数。如果本文对你有帮助,不妨点个赞,如果你是 Go 语言初学者,不妨点个关注,一起成长一起进步,如果本文有错误的地方,欢迎指出!
函数
函数的英文单词是 Function
,这个单词还有着功能的意思。在 Go 语言中,函数是实现某一特定功能的代码块。函数代表着某个功能,可以在同一个地方多次使用,也可以在不同地方使用。因此使用函数,可以提高代码的复用性,减少代码的冗余。
函数的声明
通过案例了解函数的声明有哪几部分: 定义一个函数,实现两个数相加的功能,并将相加之后的结果返回。
func Add(num1 int, num2 int) int
var sum int
sum += num1
sum += num2
return sum
通过案例可以发现,函数的声明有 5
部分:
- 1、关键字
函数的关键字是
func
,声明函数必须以 func
关键字开始。 - 2、函数名
Go
推荐使用驼峰命名的方式,和变量的命名规则一样,首字母大写的函数名可以在包外访问,小写的只能在包内访问。 - 3、参数列表 参数列表中声明了在函数体里所使用到的变量。参数列表位于函数名后面,用括号包裹着,多个参数使用逗号分隔开。
- 4、返回值列表
返回值为函数执行后的一个结果,上述代码只有一个返回值,如果有多个返回值,需要用括号包裹着,返回值之间用逗号分隔开。
少数情况下,我们会声明返回值的的名称如
func Add(num1 int, num2 int) sum int
,多数情况下是不用声明返回值的名称的。 - 5、函数体
大括号内就是函数体,存放着函数的具体实现。
函数的第
3
第 4
部分可有可无,也就是说一个函数可以没有参数和返回值。
Go 函数支持变长参数
在上面的案例中,实现的功能是对两数求和,如果我们需要对多个数求和,但又不知道具体的数量,函数的参数该怎么声明呢?这时可以声明变长参数去接收多个参数。
func main()
sum := Add(1, 2, 3, 4)
println(sum) // 10
func Add(nums ...int) int
var sum int
for _, num := range nums
sum += num
return sum
变长参数作为形式参数可以接收不定的实际参数,声明变长参数需要在类型面前加上 ...
。可变参数实际上是一个切片,可以通过 for-range
去操作。
匿名函数
通常情况下,如果一个函数只使用一次,我们就可以定义成匿名函数。
func main()
// 定义匿名函数,直接调用
result := func(num1, num2 int) int
return num1 + num2
(1, 2)
println(result)
// 2、将匿名函数赋值给一个变量,由变量调用
resultFunc := func(num1, num2 int) int
return num1 + num2
println(resultFunc(1, 2))
声明函数时,不指定函数名的函数,叫做匿名函数。匿名函数可以直接调用,也可以通过赋值给变量,由变量调用。
闭包
闭包就是一个函数和其相关引用环境组合的一个整体。
import "fmt"
// 返回值为一个匿名函数
func getSum() func(int) int
var sum int = 0
// 匿名函数
result := func(num int) int
sum += num
return sum
return result
func main()
f := getSum()
fmt.Println(f(1)) // 1
fmt.Println(f(2)) // 3
- 闭包的本质就是一个匿名函数,匿名函数里使用了定义它的函数(
getSum
)里面的变量 sum
,就组成了闭包。 - 由上述代码可知,匿名函数中所引用的变量
sum
会一直保存在内存中。
init 函数
每个 go
文件都可以包含一个 init
函数,它是一个初始化函数,用于进行初始化的操作。
var print = getNum()
func getNum() int
println("初始化变量")
return 1
func main()
println("main...")
func init()
println("init...")
执行结果:
初始化变量
init...
main...
- 根据执行结果可知,它们的执行顺序为:全局变量 →
init
函数 → main
函数。 - 多个
go
文件都有 init
函数时,执行顺序为:先执行所导入的模块的 init
函数,再执行本文件的 init
函数。
函数参数详解
形式参数与实际参数
在函数声明的地方,参数列表中的参数被称为形式参数,简称形参;而在函数调用的时候所传递的参数被称为实际参数,简称实参。举例说明:
func main()
sum := Add(1, 2)
println(sum) // 3
func Add(num1 int, num2 int) int
var sum int
sum += num1
sum += num2
return sum
Add
后面的参数被称为形参,而在 main
方法里,1
和 2
被称为实参。
值传递
基本数据类型和数组作为实参时,默认是按 值传递,即进行值拷贝,在函数内修改它们的值,原来的值不会改变。举例说明:
func main()
num1, num2 := 1, 2
Swap(1, 2)
fmt.Printf("main 函数体内打印:num1: %d, num2: %d", num1, num2)
func Swap(num1 int, num2 int)
num2, num1 = num1, num2
fmt.Printf("Swap 函数体内打印:num1: %d, num2: %d\\n", num1, num2)
执行结果:
Swap 函数体内打印:num1: 2, num2: 1
main 函数体内打印:num1: 1, num2: 2
在 Swap
函数内,num1
和 num2
的值已经相互交换,但是在 main
函数里,num1
和 num2
的值没有发生变化。
func main()
nums := [3]int0, 1, 2
Swap(nums)
fmt.Println("main 函数体内打印:nums: ", nums)
func Swap(nums [3]int)
nums[0] = 1
fmt.Println("Swap 函数体内打印:nums: ", nums)
同样传递数组,在函数内修改数组的值,原数组的值并不会改变。
前面的文章有对指针进行了介绍,指出了通过 *
操作符,可以对指针所指向的变量的值进行修改,因此如果我们想要在函数内改变外部传过来的参数的值,函数声明时,形参类型指定为指针类型。
func main()
num1, num2 := 1, 2
Swap(&num1, &num2)
fmt.Printf("main 函数体内打印:num1: %d, num2: %d", num1, num2)
func Swap(num1 *int, num2 *int)
*num2, *num1 = *num1, *num2
fmt.Printf("Swap 函数体内打印:num1: %d, num2: %d\\n", *num1, *num2)
执行结果:
Swap 函数体内打印:num1: 2, num2: 1
main 函数体内打印:num1: 2, num2: 1
通过结果可知,使用指针变量作为形参,在函数里是可以改变外部的参数的值的。
函数是一种数据类型
在 Go
里面,函数是一种数据类型,因此函数还可以有很多用法,如创建一个函数变量、将函数作为函数的形参,将函数作为函数的返回值等。
- 创建函数变量
func main()
// 创建函数变量
hl := Hello
fmt.Printf("%T\\n", hl) // func(string)
hl("cmy")
func Hello(name string)
fmt.Printf("Hello %s", name)
创建一个函数变量 hl
,打印 hl
的类型 → func(string)
,通过 hl
变量调用函数。
- 作为函数的形参
import "fmt"
func main()
Print("cmy", Hello)
func Hello(name string)
fmt.Printf("Hello %s", name)
func Print(name string, f func(string))
f(name)
定义函数 Print
,声明两个参数,一个参数是 name
,为 string
类型的,另一个参数是 f
,为函数类型。传入 cmy
和 Hello
函数,由 Print
函数去执行 Hello
函数。
- 作为函数的返回值
import "fmt"
func main()
f := Print()
f()
func Print() func()
return func()
fmt.Println("Hello,World!")
通过Print
函数返回一个匿名函数函数,这个匿名函数的功能是输出 Hello,World!
,使用 f
变量接收这个函数并调用。
- 基于函数自定义类型
type AddHandleFunc func(num1, num2 int) int
func main()
sum := GetSum(1, 2, Add)
println(sum)
func Add(num1, num2 int) int
return num1 + num2
func GetSum(num1, num2 int, handleFunc AddHandleFunc) int
return handleFunc(num1, num2)
基于函数 func(num1, num2 int) int
自定义一个类型 AddHandleFunc
,将它声明为 GetSum
的形参,然后调用 GetSum
时,因为 Add
函数和 AddHandleFunc
是等价的,因此可以将 Add
当做实参传进去。
小结
本文对函数的声明进行介绍,根据一个案例了解了其组成的 5
部分。然后介绍了其一些特点如支持变长参数、传递参数时,实参按值传递等,最后根据函数在Go中是一种数据类型的特点,说明了其一些特别用法。
以上是关于一文熟悉 Go 函数的主要内容,如果未能解决你的问题,请参考以下文章