Golang語言社群--Go語言基礎第六節函式
大家好,我是Golang語言社群主編彬哥,本篇給大家帶來的是關於Go語言中的函式。
函式定義
函式宣告語句:
function 函式名(引數列表) (返回值列表) {
// 函式體
}
注意:
1、 引數列表和返回值列表都是變數名在前,變數型別在後;
2、 Go函式支援多返回值,但並不是所有返回值都必須賦值,在函式返回時沒有被明確賦值的返回值都會被設定為預設值。
3、 函式左起的花括號”{”不能另起一行,否則會報錯;
以一個簡單的計算加法的函式為例:
func add(a int, b int) (ret int, err error) { if a<0 || b<0 { // 假設這個函式只支援兩個非負數的加法 err = errors.New("Should be non-negative numbers!") return } return a+b, nil }
如果引數列表中若干個相鄰的引數型別相同,則可以在引數列表中省略前面變數的型別宣告,例如:
func add(a, b int) (ret int, err error) {
...
}
如果返回值列表中多個返回值的型別相同,也可以用同樣的方式合併;另外,如果函式只有一個返回值,可以這樣寫:
func Add(a, b int) int {
...
}
Go語言支援多重賦值,比如:
i, j = j, i
用於交換兩個變數的值,在不支援多重賦值的語言中,交換兩個變數的內容需要引入一個臨時變數:
t = i; i = j; j = t
Go函式帶回多個返回值時,可以使用多重賦值語句,將不同的返回值賦值給不同的變數,並且允許使用匿名變數("_")接受不需要使用的返回值,例如:
func GetName() (firstName, lastName, nickName string) {
return "May", "Chan", "Chibi Maruko"
}
_, _, nickName := GetName
函式呼叫
函式呼叫非常方便,只要事先匯入該函式所在的包,就可以呼叫了:
import "mymath"
c := mymath.Add(1,2)
注意:小寫字母開頭的函式只在本包內可見,大寫字母開頭的函式才能被其它包使用。
不定引數
例如:
func foo(args ...int) { // 接受不定數量的引數,這些引數都是int型別 for _, arg := range args { fmt.Println(arg) } } foo(2,3,4) foo(1,3,7,13)
形如"...type"格式的型別只能作為函式的引數型別存在,並且必須是最後一個引數。
"...type"本質上是一個數組切片,也就是[]type,這也是為什麼上面的引數args可以用for迴圈來獲得每個傳入的引數。
如果希望不定引數傳任意型別,可以指定型別為interface{},如標準庫中的fmt.Printf()的函式原型:
func Printf(format string, args ...interface{}) {
...
}
例如:
func foo(args ...interface{}) {
for _, arg := range args {
switch arg.(type) {
case int:
fmt.Println(arg, "is an int value.")
case string:
fmt.Println(arg, "is a string value.")
case float32:
fmt.Println(arg, "is a float32 value.")
default:
fmt.Println(arg, "is an unknown type.")
}
}
}
匿名函式與閉包
匿名函式可以直接賦值給一個變數,例如:
f := func(x, y int) int {
return x+y
}
或者直接執行一個匿名函式:
func(ch chan int) {
ch <- ACK
} (reply_chan) // 花括號後面直接跟引數列表表示函式呼叫
閉包:當一個函式內部巢狀另一個函式定義時,內部的函式體可以訪問外部函式的區域性變數。
a := func() (func()) {
var i int = 10
return func(){
fmt.Printf("i=%dn", i)
i++
}
}
c1 := a()
c2 := a()
c1() // 10
c1() // 11
c1() // 12
c2() // 10
c1和c2是建立在同一個函式上,但作用在同一個區域性變數的不同例項上的兩個不同的閉包。