什麼是Function? 我覺得上面這張圖說明的太好了: 一個function是一段獨立的程式碼,就好像一個黑盒子一樣, 我們餵進去0到多個參數進去後, 這個黑盒子就會吐出0-多個結果給我們。
目前我們已經寫過了第一個function:
func main() {}
寫法可以很容易理解:
func plus(a int, b int) int {
return a + b
}
以上表示說, 我們建立了一個function叫作plus, 可以傳入2個type均為int的參數a和b, function傳回的參數type也為int。
如果傳入function的參數都是相同type, 那麼只要宣告一次就好:
func plus(a, b, c int) int {
return a + b + c
}
呼叫function就跟我們熟悉的一樣, 使用 name(args)
:
function main(){
res := plus(1,2)
}
Go內建支援function的多個傳回值(multiple return values), 在Go裏面是非常常見的手法, 例如從function傳回結果(result)和錯誤值(error)。
以下(int, int)
表示這個function傳回兩個ints:
func vals() (int, int){
return 3, 7
}
使用該function的時候, 我們可以利用 multiple assignment 來接收兩個不同的傳回值:
a, b := vals()
如果我們只要傳回值的子集合, 就是不要某些傳回值, 那麼就利用blank identifier _ :
_, c := vals()
Go也支援 Variadic function(可接收可變數量參數的函式)。
func sum(nums ...int) {
fmt.Print(nums, " ")
total := 0
for _, num := range nums {
total += num
}
fmt.Println(total)
}
呼叫時候可以傳入不同數量的參數:
sum(1, 2)
sum(1, 2, 3)
如果要傳入的參數已經存放在slice裡了, 那要用func(slice...)
的語法如下:
nums := []int{1,2,3,4}
sum(nums...)
Go也支援匿名函式(anonymous functions), 用來製作 closure 。
func intSeq() func() int {
i := 0
return func() int {
i += 1
return i
}
}
這裡的intSeq
函式傳回了另外一個我們定義的匿名函式, 這個傳回的函式將變數i
封裝起來形成closure。
當我們呼叫intSeq
, 把intSeq
的值(一個function)給nextInt
, 這個nextInt
有其自己的i
值, 每次我們呼叫nextInt
, i
就會一直更新, 例如:
fmt.Println(nextInt())
fmt.Println(nextInt())
fmt.Println(nextInt())
newInts := intSeq()
fmt.Println(newInts())
將會得到:
1
2
3
1
Go也支援遞迴函式(recursive functions)
func fact(n int) int {
if n == 0 {
return 1
}
return n * fact(n-1)
}
Go支援 pointer(指標), 允許傳址(pass reference to values)。
func zeroval(ival int) {
ival = 0
}
zeroval這個function具有參數型別為int, 因此參數就會傳值(value)到函式裡面, 也就是zeroval
會得到ival
的值拷貝。
若我們呼叫zeroval
:
i := 1
zeroval(i)
fmt.Println(i)
我們會得到結果為1, 並不會影響原來的 i
。
就如同大家所熟悉的C/C++:
func zeroptr(iptr *int) {
*iptr = 0
}
zeroptr有一個iptr
參數, 型別為 *int
表示是一個整數型態的指標(pointer)。
呼叫zeroptr
:
i := 1
zeroptr(&i)
fmt.Println( i)
&i
會給 i
的記憶體位址, 這裡i的數值就被改動了, 結果為0。
這系列筆記文章都來自於以下局部翻譯或整理:
An introduction to programming in Go