函數編寫的順序無關緊要,鑒于可讀性,最好把main()函數寫在檔案的前面
Go裡面有三中類型的函數:
普通的帶有名字的函數
匿名函數或者lambda函數
方法(Methods)
注意:
**go語言不允許函數重載,沒有泛型概念
**函數簽名:函數參數,傳回值以及它們的類型被統稱為函數簽名
**空白符“_”
傳回值:
函數可以傳回多個值,相當于python的元組。
- 如果一個函數需要傳回四五個值,我們可以傳遞一個切片給函數(如果傳回值具有相同類型),或者傳遞一個結構體(如果傳回值具有不同類型)。因為傳遞一個指針允許直接修改原來的值,消耗更少。
- 命名傳回值和非命名傳回值
- func getX2AndX3(input int) (int, int)
- func getX2AndX3_2(input int) (x2 int, x3 int)
- 函數參數:
- 按值傳遞參數:傳遞的是參數的副本,接受參數副本之後,修改值,不會影響原來的變量。
- 按引用傳遞參數:将參數的位址傳遞給函數,可以修改參數原來的值。函數調用時,像切片,字典,接口,通道這樣的引用類型都是預設使用引用傳遞,及時沒有顯示的指出指針
- 傳遞變長參數:
- 如果函數的最後一個參數是采用…type的形式,那麼為變長參數
func Greeting(prefix string, who ...string)
Greeting("hello:", "Joe", "Anna", "Eileen")
變量who 的值為 []string{"Joe", "Anna", "Eileen"}
- 如果可變長參數類型一樣,可以使用slice或者數組左參數
- 如果可變長參數的類型不一樣,可以使用結構和空接口做參數
- 結構:參數個數和類型已知,但不行同
- 空接口:參數個數和類型未知,一般會使用for-range循環以及switch對結構中每個參數類型進行判斷
func typecheck(..,..,values … interface{}) {
for _, value := range values {
switch v := value.(type) {
case int: …
case float: …
case string: …
case bool: …
default: …
}
}
}
- defer和追蹤
- 關鍵字defer允許我們推遲到函數傳回之前,或者任意位置執行return語句之後一刻才執行猴哥語句或函數。類似其他語言的finally,一般用于釋放某些已配置設定的資源。
- 使用defer語句實作代碼追蹤
- 使用defer語句來記錄函數的參數與傳回值
當有多個defer行為被注冊時,它們會逆序執行(類型棧,即後進先出)
- 内置函數
- Go語言擁有一些不需要進行導入操作就可以使用的内置函數。
- 遞歸函數
- 函數調用函數自身
- 将函數作為參數
- 函數可以作為其他函數的參數進行傳遞,然後在其它函數内調用執行,一般稱之為回調
- 匿名函數(閉包):
- 匿名函數不能夠獨立存在,但是可以指派給變量,這樣變量就儲存了該函數的位址,然後通過變量名對函數進行調用
fplus := func(x, y int) int { return x + y };fplus(3,4)
- defer配合匿名函數使用
- 應用閉包:将函數作為傳回值
- 閉包函數儲存并積累其中的變量的值,不管外部函數推出與否,它都能夠繼續操作外部函數中的局部變量。
func Add2() (func(b int) int)
func Adder(a int) (func(b int) int)
- 使用閉包調試調試
- 計算函數執行時間:
- 使用time包中的Now()和Sub函數
- start := time.Now(); …;end = time.Now();dellta := end.Sub(start)