func 函数名 (形参列表) (返回值参数列表) {
...
return 返回值列表
}
基本结构
- GO中函数不允许重载
package main
import "fmt"
func add(a int, b int) int {
return a + b
}
func main() {
fmt.Println(add(1, 1))
}
入参
入参类型简化书写
package main
import (
"fmt"
)
func add(num1, num2 int) int { // 改成func add(num1 int, num2) int会报错
return num1 + num2
}
func main() {
fmt.Printf("%T", add) // func(int, int) int
}
支持可变参数,被作为slice处理
package main
import (
"fmt"
)
func argsDemo(args ...int) {
fmt.Printf("%v, %T\n", args, args)
for _, value := range args {
fmt.Println(value)
}
}
func main() {
argsDemo(1, 2, 3, 4, 5, 6)
}
出参
返回值参数只有一个时,返回值参数列表的括号可以省略,多个返回值参数必须带括号
支持按位置的多返回值,接受也是按位置逐一接收
package main
import "fmt"
func div(num1 int, num2 int) (int, int) {
//必须按照位置返回参数
return num1 / num2, num1 % num2
}
func main() {
merchant, remainder := div(6, 3)
fmt.Println(merchant, remainder)
}
支持具名返回值,接收是按位置接收
package main
func div1(num1 int, num2 int) (int, int) {
//必须按照位置返回参数
return num1 / num2, num1 % num2
}
func div2(num1 int, num2 int) (merchant int, remainder int) {
//return 1, 1 // 可以按照位置返回参数
merchant = num1 / num2
remainder = num1 % num2
return // 可以根据名称自动返回
}
函数作为参数
package main
import (
"fmt"
"math"
)
// run1
// 接收两个参数,第一个参数是一个float64,第二个参数是一个函数,该函数接收一个float64的参数并返回一个float64的参数
func run1(num float64, function func(float64) float64) float64 {
fmt.Printf("num=%f, func=%T\n", num, function)
return function(num)
}
// f 定义一个类型 f,该类型为一个函数类型,其中该函数入参为一个float64,以及返回值是一个float64
type f func(float64) float64 //函数可以通用
func run2(num float64, function f) float64 {
fmt.Printf("num=%f, func=%T\n", num, function)
return function(num)
}
func main() {
fmt.Println(run1(-3.14, math.Abs))
// num=-3.140000, func=func(float64) float64
// 3.14
fmt.Println(run2(-3.14, math.Abs))
// num=-3.140000, func=main.f
// 3.14
}
匿名函数
- 定义匿名函数时直接调用
- 将匿名函数赋给变量,通过变量调用,局部变量和全局变量会导致函数可调用范围不一样
package main
import "fmt"
func main() {
result := func(num1 int, num2 int) int { return num1 + num2 }(1, 1)
fmt.Println(result)
f := func(num1 int, num2 int) int { return num1 - num2 }
fmt.Println(f(1, 1))
}
函数闭包
闭包函数相当于内部维护了一部分共享的数据,每次调用都会使用同一部分数据而非副本,当然也可以不维护
package main
import "fmt"
func adder() func(int) int {
sum := 0
return func(i int) int {
sum = i + sum
return sum
}
}
func main() {
f := adder()
sum := f(1)
fmt.Println(sum) // 1
sum = f(1)
fmt.Println(sum) // 2
}
内置函数
len、cap
package main
import (
"fmt"
)
func main() {
// len 内置函数返回 v 的长度
// 根据 v 的类型取值有:
// 数组:数组v中元素的数量
// 数组指针:数组*v中的元素
// 切片、映射:v 中元素的数量,若 v 为 nil,则返回 0
// 通道:
// 详见Go语言规范 长度和容量 一节
fmt.Println(len("abc"))
// cap 内置返回 v 的容量
// 根据 v 的类型取值有:
// 数组:v 中元素的数量,同 len
// 数组指针:*v 中元素的数量
// 切片:二次切片可用的最大长度,若 v 为 nil,cap(v) 为 0
// 通道:通道缓存容量,若 v 为 nil,cap(v) 为 0
fmt.Println(cap([]int{1, 2, 3}))
}
new、make
package main
import (
"fmt"
)
func main() {
// func new(Type) *Type
// new 内置函数用于申请内存
// 入参:第一个参数是一个 Type 类型参数
// 出参:返回一个 *Type 指针,指针指向一个新的 Type 类型数据的零值
num := new(int)
fmt.Println(num, *num) // 0xc00000a0b8 0
// func make(t Type, size ...IntegerType) Type
// 内置函数 make 用于针对某类型的对象申请内存和初始化,类型有 slice、map、chan(only)
// slice:size 指定长度,slice的容量等于其长度,第二个整数参数可以指定一个不等于长度的容量,容量不能小于长度
// 例如
// map:
// channel:以 size 为指定容量创建和初始化 channel buffer,若 size 为 0,或者 size 被省略,channel 为无 buffer
a := make([]int, 0, 10)
fmt.Printf("%T, %v", a, a) // []int, []
}
recover、painc
见yi’chang