Go语言中支持函数、匿名函数和闭包
func 函数名(参数)(返回值){
函数体
}
func intSum(x, y int) int {
return x + y
}
func helloWord() {
fmt.Println("hello word")
}
func main() {
c := intSum(10, 20)
fmt.Println(c)
helloWord()
}
可变参数放在固定参数后边,通过...来实现,可变参数为一个切片
func intSum(x int, y ...int) int {
sum := x
for _, v := range y {
sum += v
}
return sum
}
func intSum(x int, y ...int) (int, int) {
sum := x
sub := x
for _, v := range y {
sum += v
sub -= v
}
return sum, sub
}
func intSum1(x, y int) (sum int) {
sum = x + y
return
}
全局变量:全局变量是定义在函数外部的变量,在程序运行周期内都有效。函数中可访问
package main
import "fmt"
var num int64 = 10
func test() {
fmt.Println(num)
}
func main() {
test()
}
局部变量:局部变量分两种,一种是在函数内定义,一种是语句块内(if、for、switch)定义。如果和全局变量同名,有限访问局部变量。
package main
import "fmt"
var num int64 = 10
func test(x int) {
num := 100
fmt.Println(num)
if x > 10 {
z := 10 // 只在if中生效
fmt.Println(z)
}
}
func main() {
test(11)
}
定义函数类型
type calculation func(int, int) int
func add(x, y int) int {
return x + y
}
func main() {
var c calculation
c = add
num1 := c(10, 20)
fmt.Println(num1)
}
高阶函数分为函数作为参数和函数作为返回值
func add(x, y int) int {
return x + y
}
func calc(x, y int, op func(int, int) int) int {
return op(x, y)
}
func main() {
ret := calc(10, 20, add)
fmt.Println(ret) // 30
}
func do(s string) (func(int, int) int, error) {
switch s {
case "+":
return add, nil
case "-":
return sub, nil
default:
err := errors.New("无法识别的标识符")
return nil, err
}
}
匿名函数:匿名函数就是没有函数名的函数,如果想调用需要保在某个变量中或者立即执行函数。匿名函数多用于回调函数和闭包
func(参数)(返回值){
函数体
}
func main() {
add := func(x, y int) {
fmt.Println(x + y)
}
add(10, 20) // 通过变量调用匿名函数
func(x, y int) { // 自动执行函数:匿名函数定义完加()直接执行
fmt.Println(x + y)
}(20, 20)
}
闭包:闭包指一个函数和其相关的应用环境组合而成的实体。闭包=函数+应用环境
func adder() func(int) int {
var x int
return func(y int) int {
x += y
return x
}
}
func main() {
var f1 = adder()
fmt.Println(f1(10)) // 10
fmt.Println(f1(10)) // 20
f2 := adder()
fmt.Println(f2(30)) // 30
fmt.Println(f2(30)) // 60
}
变量f在一个函数并且引用了其外部作用域的x变量,此时f就是一个闭包。在f生命周期内,变量x一直有效
闭包一:
func adder(x int) func(int) int {
return func(y int) int {
x += y
return x
}
}
func main() {
var f1 = adder(10)
fmt.Println(f1(10)) // 20
fmt.Println(f1(10)) // 30
f2 := adder(20)
fmt.Println(f2(30)) // 50
fmt.Println(f2(30)) // 80
}
闭包二:
func makeSuffixFunc(suffix string) func(string) string {
return func(name string) string {
if !strings.HasSuffix(name, suffix) {
return name + suffix
}
return name
}
}
func main() {
jpgFunc := makeSuffixFunc(".jpg")
txtFunc := makeSuffixFunc(".txt")
fmt.Println(jpgFunc("图片"))
fmt.Println(txtFunc("图书"))
}
闭包三:
func calc(base int) (func(int) int, func(int) int) {
add := func(i int) int {
base += i
return base
}
sub := func(i int) int {
base -= i
return base
}
return add, sub
}
func main() {
f1, f2 := calc(10)
fmt.Println(f1(1), f2(1)) // 11,10
}
defer语句会延迟处理,并且按照倒序执行。defer函数的参数是在defer语句出现的位置做计算的,而不是在函数运行的时候做计算的,即所在函数结束的时候计算的。
func main() {
fmt.Println("start")
defer fmt.Println("defer1")
defer fmt.Println("defer2")
fmt.Println("end")
}
// 顺序为start end defer2 defer1
func foo(n int) int {
fmt.Println("n1:", n)
defer fmt.Println("n:", n)
n += 100
fmt.Println("n2:", n)
return n
}
func main() {
foo(100)
}
// 输出为 n1:100 n2:200 n:100
func f1() int {
x := 5
defer func() {
x++
}()
return x
}
func f2() (x int) {
defer func() {
x++
}()
return 5
}
func f3() (y int) {
x := 5
defer func() {
x++
}()
return x
}
func f4() (x int) {
defer func(x int) {
x++
}(x)
return 5
}
func main() {
fmt.Println(f1()) // 5
fmt.Println(f2()) // 6
fmt.Println(f3()) // 5
fmt.Println(f4()) // 5
}
func calc(index string, a, b int) int {
ret := a + b
fmt.Println(index, a, b, ret)
return ret
}
func main() {
a := 1
b := 2
defer calc("1", a, calc("10", a, b))
a = 0
defer calc("2", a, calc("20", a, b))
b = 1
}
// 10 1 2 3
// 20 0 2 2
// a,b 0 1
// 2 0 2 2
// 1 1 3 4
// defer后面的函数参数优先计算
加深理解:defer函数的参数是在defer语句出现的位置做计算的,而不是在函数运行的时候做计算的,即所在函数结束的时候计算的。
func foo(n int) int {
fmt.Println("n1=", n)
defer fmt.Println("n=", n)
n += 100
fmt.Println("n2=", n)
return n
}
func main() {
var i int = 100
foo(i)
}
// 输出结果为 n1=100; n2=200; n=100 n为defer函数的参数
func foo(n int) int {
fmt.Println("n1=", n)
defer func() {
n += 100
fmt.Println("n=", n)
}()
n += 100
fmt.Println("n2=", n)
return n
}
func main() {
var i int = 100
foo(i)
}
// 结果为:n1=100; n2=200; n=300 此时的n不是defer后边的参数
内置函数 | 介绍 |
close | 主要用于关闭channel |
len | 用来求长度,比如string、array、slice、map、channel |
new | 用来分配内存,主要用来分配值类型,比如int、struct。返回的是指针 |
make | 用来分配内存,主要用来分配引用类型,比如chan、map、slice |
append | 用来追加元素到数组、slice中 |
panic和recover | 用来做错误处理 |
make和new的区别
使用panic/recover模式来处理错误。panic任何地方都可以引发,但recover只能在defer调用的函数中有效
func funcA() {
fmt.Println("func A")
}
func funcB() {
defer func() {
err := recover()
//如果程序出出现了panic错误,可以通过recover恢复过来
if err != nil {
fmt.Println("recover in B")
}
}()
panic("panic in B")
}
func funcC() {
fmt.Println("func C")
}
func main() {
funcA()
funcB()
funcC()
}