Go 语言笔记:函数
函数定义
函数声明,主要包含
func
关键字, 返回值类型return_type
(如c int
或不指定变量名c
),和入参parameter_list
(如a int, b int
)
go
// 函数定义结构
func name ([parameter_list]) [return_type] {
函数体
}
// 函数定义示例
func add(a int, b int) (c int) {
return a + b;
}
Go
函数不支持重载
同一个包不能相同名称的函数,如下编译器会报错:foo redeclared int this package
go
func foo() int {
return 2;
}
func foo(a int) (b int, c int) {
return 2, 3;
}
函数返回值
Go
函数支持返回值不写变量名,如下面的减法操作,c
可忽略掉,且只有一个返回值时,不需要()
包装
go
// 当返回值存在命名,`return` 可以不指定返回值变量
func add(a int, b int) (c int) {
c = a + b
return
}
// 当返回值不存在命名,`return` 后面必须显式返回结果
func sub(a int, b int) int {
return a - b
}
函数返回值的接收
函数的返回值可以赋给变量, 同时某些返回值也可以标识符
_
忽略接收
go
func add(a int, b int) (c int) {
c = a + b
return
}
func calculate(a int, b int) (sum int, sub int) {
sum = a + b
sub = a - b
return
}
fun main() {
sum := add(100, 200)
println(sum) // 300
sum, sub := calculate(100, 200)
println(sum, sub) // 300, -100
_, sub := calculate(200, 200)
println(sub) // 0
// 注意这里已经不存在新的变量,属于重新赋值,使用 `=` 即可
sum, _ = calculate(200, 200)
println(sub) // 0
}
函数类型
函数也是一种类型,可以赋值给变量
go
package main
import "fmt"
// 声明函数类型
type calc func(a, b int) int
func add(a, b int) int {
return a + b
}
func operate(op calc, a int, b int) int {
return op(a, b)
}
func main() {
// 将函数类型赋值给变量 `function`
function := add
// 打印函数地址
println(function)
// 将函数类型作为入参
sum := operate(function, 5, 10)
println(sum)
}
可变参数
可变参数,实际上是一个slice切片类型,可以通过下标索引的方式访问,可以使用内置函数
len
来统计其长度,且可变参数只能放在函数入参的最后一个位置
func add(a int, args... int) int {
函数体
}
func concat(s string, arg ...string) string {
str := s
for i := 0; i < len(arg); i++ {
str += arg[i]
}
return str
}
main 函数 和 init 函数
- main 函数只能用在 package main 包中,且 package main 包中必须包含 main 函数
- main 函数不能有入参,命令行传入的参数可以使用
os.Args
获取,命令行开关打开需要导入flag
包 - init 函数可以出现在任何的 package 中,是可选的,也可以不出现
- main 和 init 函数不需要手动调用,
Go
程序会自动执行这两个函数
函数作用域
- 在函数体内部声明的变量是局部变量,生命周期仅限于函数内部
- 在函数体外部声明的变量是全局变量,生命周期作用于整个包,如果函数名是大写的,做作用于整个程序
go
package main
import "fmt"
var age int
func main() {
age = 18
println(age)
foo()
}
func foo() {
age := 20
println(age)
foo2()
}
func foo2() {
println(age)
}
输出:
18
20
18
匿名函数
匿名函数,即没有函数名,由函数声明和函数体组成
go
func main() {
// 匿名函数赋值给变量 foo
foo := func(a, b int) int {
return a + b
}
println(foo(2, 3))
}
闭包
闭包是函数和与其相关的引用环境组合而成的结构实体,函数可以存储到变量中作为参数传递给其他函数
go
package main
import "fmt"
func calculate() func(int) int {
var x int
return func(d int) int {
x += d
return x
}
}
func main() {
f := calculate()
fmt.Println(f(1)) // 1
fmt.Println(f(10)) // 11
fmt.Println(f(100)) // 111
println(calculate()(1)) // 1
println(calculate()(10)) // 10
println(calculate()(100)) // 100
}
上述的 f := calculate()
操作,会将函数变量赋值给变量 f
, f
就此成为了一个闭包,f
保存着对 x
的引用,由于 f
有着指向 x
的指针,因此后面重复调用 f
时,f
指向 x
的值还是上一次的结果,导致了 x
逃逸了,生命周期没有结束。而多次调用 calculate()(x)
方法是分别返回了不同的闭包,因此函数体内的 x
不会对下一个闭包产生影响,因为他们是不同的闭包