這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
Go程式設計語言:支援並發、記憶體回收的編譯型系統級程式設計語言!本文主要是按照無聞的《Go 編程基礎》開源視頻學習並記錄筆記。
一、函數function
1、基本概念
函數是基本的代碼塊,用於執行一個任務。
Go 語言最少有個 main() 函數。
函式宣告告訴了編譯器函數的名稱,傳回型別,和參數。
Go 語言標準庫提供了多種可動用的內建的函數。例如,len() 函數可以接受不同型別參數並返回該類型的長度。如果我們傳入的是字串則返回字串的長度,如果傳入的是數組,則返回數組中包含的函數個數。
2、函數定義
函數定義格式如下:
func function_name( [parameter list] ) [return_types] { 函數體}
函數定義解析:
func:函數由 func 開始聲明
function_name:函數名稱,函數名和參數列表一起構成了函數簽名。
parameter list:參數列表,參數就像一個預留位置,當函數被調用時,你可以將值傳遞給參數,這個值被稱為實際參數。參數列表指定的是參數類型、順序、及參數個數。參數是可選的,也就是說函數也可以不包含參數。
return_types:傳回型別,函數返回一列值。return_types 是該列值的資料類型。有些功能不需要傳回值,這種情況下 return_types 不是必須的。
函數體:函數定義的代碼集合。
樣本:
/* 函數返回兩個數的最大值 */func max(num1, num2 int) int { /* 聲明局部變數 */ var result int if (num1 > num2) { result = num1 } else { result = num2 } return result }
3、函數特性
- Go 函數
不支援嵌套、重載和預設參數
- Go 函數
支援無需聲明原型、不定長度變參、多傳回值、命名傳回值參數、匿名函數、閉包
- 定義函數使用關鍵字
func,且左大括弧不能另起一行
函數也可以作為一種類型使用
ackage mainimport "fmt" func main() { A(1, 2, 3, 4 ,5)}// ... 不定長變參func A(a ...int) { fmt.Println(a) }
輸出:
➜ myfirstgo go run func.go[1 2 3 4 5]
不定長變參特性:
1、不可以在不定長變參後邊添加其他參數 func b(a ...int, b string), 這種寫法是錯誤的
2、不定長參數可以放在其他參數後邊 func b(b string, a ...int)
4、匿名函數
func main() { // 將一個函數賦值一個變數,該變數是函數類型 a := func(){ fmt.Println("匿名函數")} // 調用 a()}
5、閉包
/*** 閉包函數** 該閉包函數接收一個int型參數,其傳回值是函數類型**/func closure(x int) func(int) int { fmt.Println("%p\n", &x) return func (y int) int { fmt.Println("%p\n", &x) fmt.Println(x) fmt.Println(y) return x + y }}func main() { f := closure(10); fmt.Println(f(1)) fmt.Println(f(2))}
列印結果:
➜ myfirstgo go run func.go%p 0xc42000e228%p 0xc42000e22810111%p 0xc42000e22810212➜ myfirstgo
6、defer
- defer 的執行方式類似其他語言中的
解構函式,在函數體執行結束後按照調用順序的相反順序逐個執行
- 即使函數發生
嚴重錯誤也會執行
- 支援匿名函數的調用
- 常用於
資源清理、檔案關閉、解鎖以及記錄時間等操作
- 通過與匿名函數配合可在return之後
修改Function Compute結果
- 如果函數體內某個變數作為defer時匿名函數的參數,則在定義defer時即已經獲得了拷貝,否則則是引用某個變數的地址
- Go沒有異常機制,但有
panic/recover 模式來處理錯誤
Panic 可以在任何地方引發,但 recover 只有在 defer 調用的函數中有效
簡單的測試:
func main() { fmt.Println("a") defer fmt.Println("b") defer fmt.Println("c")}
上邊的執行會列印什麼結果呢? 會列印:a b c 嗎?
讓我們實際執行一下:
myfirstgo go run func.goacb
實際列印的結果為:a c b
defer 的執行方式類似其他語言中的解構函式,在函數體執行結束後按照調用順序的相反順序逐個執行
使用閉包
func main() { for i := 0; i < 3; i++ { // defer 普通調用 // defer fmt.Println(i) // 列印 2 1 0 // 使用閉包,引用局部變數 defer func () { fmt.Println(i) }() } }
列印結果:
➜ myfirstgo go run func.go333
panic 使用樣本:
func main() { A() B() C()}func A() { fmt.Println("FUNC A")}func B() { // 匿名函數,如果沒有參數,則末尾需要使用括弧 defer func() { if err := recover(); err != nil { fmt.Println("Recover is B") } }() panic("B panic")}func C() { fmt.Println("FUNC C")}
列印結果:
➜ myfirstgo go run func.goFUNC ARecover is BFUNC C➜ myfirstgo