Table of Contents
<span class="ez-toc-title-toggle"><a href="#" class="ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle" aria-label="顯示/隱藏內容目錄"><span class="ez-toc-js-icon-con"><span class=""><span class="eztoc-hide" style="display:none;">Toggle</span><span class="ez-toc-icon-toggle-span"><svg style="fill: #999;color:#999" xmlns="http://www.w3.org/2000/svg" class="list-377408" width="20px" height="20px" viewBox="0 0 24 24" fill="none"><path d="M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z" fill="currentColor"></path></svg><svg style="fill: #999;color:#999" class="arrow-unsorted-368013" xmlns="http://www.w3.org/2000/svg" width="10px" height="10px" viewBox="0 0 24 24" version="1.2" baseProfile="tiny"><path d="M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z"/></svg></span></span></span></a></span>
函數
輸入的參數可多個, 返回也可多個
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) Durationt是時間值。
此方法是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
1package 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