函數
輸入的參數可多個, 返回也可多個
func 函數名(參數)(返回值){
函數體
}
範例:
package main
import "fmt"
func main() {
fmt.Println(sum(2, 3)) //5
x, y := getXYValue()
fmt.Printf("x:%d y:%d", x, y) //x:1 y:2
var f func() //指定function類型
f = process //把process這個func指定給f
f() // 調用f等於調用process
}
func sum(x, y int) int {
return x + y
}
func getXYValue() (x, y int) {
x = 1
y = 2
return x, y
}
func process() {
fmt.Println("use process function")
}
匿名函數
package main
import "fmt"
func main() {
//匿名函數
f := func(name string) {
fmt.Println("hello,", name)
}
f("bocky") //hello, bocky
fmt.Println("===")
iterator([]int{1, 2, 3, 4, 5, 6}, func(value int) { //函數沒有名稱
fmt.Println(value)
})
}
func iterator(arr []int, ff func(int)) { // 這裡的函數是有名稱ff
for _, value := range arr {
ff(value)
}
}
閉包
閉包 = 函數+引用環境
範例:
package main
import "fmt"
func main() {
//str := "Bocky" // IDE會出現str declared but not used
f := func() {
str := "Abby"
fmt.Println(str) //Abby
}
f()
// 閉包擁有記憶性
fmt.Println("======")
add1 := add(1)
fmt.Println(add1()) //2
fmt.Println(add1()) //3
fmt.Printf("%p\n", &add1) //0xc000006030
fmt.Println("======")
add2 := add(200)
fmt.Println(add2()) //201
fmt.Println(add2()) //202
fmt.Printf("%p\n", &add2) //0xc000006038
fmt.Println("======")
bocky := user("bocky")
name, hp := bocky()
fmt.Println(name, hp) //bocky 1000
fmt.Println("======")
amy := user("amy")
name2, hp2 := amy()
fmt.Println(name2, hp2) //amy 1000
}
func add(v1 int) func() int {
return func() int {
v1++
return v1
}
}
func user(name string) func() (string, int) {
hp := 1000
return func() (string, int) {
return name, hp
}
}
可變參數
在實際開發中,總有一些函數的參數個數是在編碼過程中無法確定的,
當有狀況是需要實現類似的接口時,就會用到”可變參數”了。
package main
import (
"bytes"
"fmt"
)
func main() {
//可變參數
funx1(1)
funx1(1, 2, 3, 5)
funx2(11) //11 int
funx2("1234") //1234 string
funx2(1.23) //1.23 default
funx2(func() () { return }) //0x96ca00 default
fmt.Println("=======")
fmt.Println(funx3("hello "))
fmt.Println(funx3("hello ", "I'm ")) //hello I'm
fmt.Println(funx3("hello ", "I'm ", "Bocky!")) //hello I'm Bocky!
fmt.Println("=======")
Tprint("A","B","C")
}
func funx1(args ...int) { //不確定會傳多少個int的時候可以使用...但一定要是int類型
for _, arg := range args {
fmt.Println(arg)
}
}
func funx2(args ...interface{}) { //任一類型的可變參數
for _, arg := range args {
switch arg.(type) {
case int:
fmt.Println(arg, "int")
case string:
fmt.Println(arg, "string")
case float32:
fmt.Println(arg, "float32")
default:
fmt.Println(arg, "default")
}
}
}
func funx3(strs ...string) string {
var b bytes.Buffer
for _, s := range strs { // 依序遍歷strs內的string
b.WriteString(s)
}
return b.String()
}
//下方Tprint會call funx4來執行print的動作
func Tprint(params ...interface{}) {
funx4(params)
}
func funx4(params ...interface{}) {
for _, value := range params {
fmt.Println(value)
}
}
計算函數時間
想要獲取計算某個任務從開始到結束的運行時間,我們可以使用time包中的Slice函數,用法:
func Since (t Time) Duration
t是時間值。
此方法是time.Now().Sub(t)的快捷方式
package main
import (
"fmt"
"time"
)
func main() {
//func Since(t Time)Duration
//time.Now().sub(t
testTime()
}
func testTime() {
start := time.Now()
sum := 0
for i := 0; i < 1000000000; i++ {
sum++
}
duration := time.Since(start)
fmt.Println("function執行時間:", duration)
}
遞迴
費波那契數列
1,1,2,3,5,8,13 ,...
package main
import "fmt"
func main() {
//遞迴
result := 0
for i := 1; i <= 10; i++ {
result = fibonacci(i)
fmt.Printf("fibonacci(%2d) -> %3d\n", i, result)
}
}
func fibonacci(n int) (rtn int) {
if n <= 2 {
rtn = 1
} else {
rtn = fibonacci(n-1) + fibonacci(n-2)
}
return
}
defer 延遲執行
- 用於資源的釋放,會在函數返回之前進行調用,簡單來說就是宣告 function “結束前”的動作。
- 先進後出
- 會保留當下狀態
簡單的範例:
package main
import (
"fmt"
)
func main() {
fmt.Println("defer start")
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
fmt.Println("defer stop")
}
結果:
defer start
defer stop
3
2
1
package main
import (
"fmt"
)
func main() {
num := 1
x := addOne(num)
fmt.Printf("Result is %d\n",x)
}
func closeProcess() {
fmt.Println("close process")
}
func addOne(x int) int {
fmt.Println("Start process")
defer closeProcess() // function結束前返回
if x > 2 {
fmt.Println("x > 2")
return x * 20
} else {
fmt.Println("x <=2")
return x + 1
}
}
結果:
Start process
x <=2
close process
Result is 2