Function
函數定義的方式:func plus(a int, b int) int {}
package main
import "fmt"
func plus(a int, b int) int {
return a + b
}
// 相同類型的入參可以這樣定義
func plusPlus(a, b, c int) int {
return a + b + c
}
func main() {
res := plus(1, 2)
fmt.Println("1+2 =", res)
res = plusPlus(1, 2, 3)
fmt.Println("1+2+3 =", res)
}
多傳回值
多傳回值是Go的一大特色之一,非常有用。
package main
import "fmt"
func vals() (int, int) {
return 3, 7
}
func main() {
a, b := vals()
fmt.Println(a)
fmt.Println(b)
_, c := vals()
fmt.Println(c)
}
可變參數函數
這裡的可變是指入參長度可變。可變參數函數的入參類型為:...類型:
package main
import "fmt"
// 傳入之後,nums的實際類型就是[]int
func sum(nums ...int) {
fmt.Print(nums, " ")
total := 0
for _, num := range nums {
total += num
}
fmt.Println(total)
}
func main() {
// 調用時隻需要按正常方式調用
sum(1, 2)
sum(1, 2, 3)
// 也可以将已經是slice的結構傳入,但要在其後面加...(真神奇)
nums := []int{1, 2, 3, 4}
sum(nums...)
}
上面的程式輸出:
$ go run variadic-functions.go
[1 2] 3
[1 2 3] 6
[1 2 3 4] 10
Closure閉包
這個翻譯實在拗口。Go 支援可以形成閉包的匿名函數。當你想内聯定義一個函數而不必命名時,匿名函數很有用。有些朋友已經想到了,沒錯,跟lambda有點像。閉包本質上是一個結構體,包含了函數入口和函數内定義的變量。
package main
import "fmt"
func intSeq() func() int {
i := 0
return func() int {
i++
return i
}
}
func main() {
nextInt := intSeq()
fmt.Println(nextInt())
fmt.Println(nextInt())
fmt.Println(nextInt())
newInts := intSeq()
fmt.Println(newInts())
}
上面的程式輸出:
$ go run closures.go
1
2
3
1
閉包,到底包住了什麼呢?比如上面的例子,包住了一個“函數變量i”,每個intSeq函數都捕捉着自己的i,在每次調用函數時,i都實作有狀态變化。神奇,這搞出了類成員變量的感覺。
遞歸
遞歸兩要素:1. 自己調自己;2. 有終止條件。
package main
import "fmt"
func fact(n int) int {
// 遞歸終止條件
if n == 0 {
return 1
}
return n * fact(n-1)
}
func main() {
fmt.Println(fact(7))
var fib func(n int) int
// 閉包也可以是遞歸的,但這需要var在定義閉包之前用類型顯式聲明閉包
fib = func(n int) int {
if n < 2 {
return n
}
return fib(n-1) + fib(n-2)
}
// 在main内部來說,fib就是一個閉包
fmt.Println(fib(7))
}
上面的程式輸出:
$ go run recursion.go
5040
13
每日一Tip
Go的函數非常靈活,結合閉包的使用,可以實作類似Java的lambda效果。