📕
Go 語言程式設計入門
  • 最新消息
  • 中文版更新日誌
  • 譯者誌謝
  • 01-起步走
    • 01.01-檔案與資料夾
    • 01.02-終端機(Terminal)
    • 01.03-文字編輯器
    • 01.04-Go 的工具
  • 02-你的第一個程式
    • 02.01-如何讀 Go 程式
    • 02.02-問題
  • 03-型別
    • 03.01-數字
    • 03.02-字串
    • 03.03-問題
  • 04-變數
    • 04.01-如何命名變數
    • 04.02-Scope(變數的作用範圍)
    • 04.03-常數(Constant)
    • 04.04-定義多個變數
    • 04.05-範例程式
    • 04.06-問題
  • 05-控制結構
    • 05.01-For
    • 05.02-If
    • 05.03-switch
    • 05.04-問題
  • 06-Array、Slice 與 Map
    • 06.01-陣列(Array)
    • 06.02-Slice
    • 06.03-Map
    • 06.04-問題
  • 07-函式
    • 07.01-你的第二個函式
    • 07.02-回傳多個值
    • 07.03-參數個數可變的函式(Variadic Function)
    • 07.04-Closure
    • 07.05-遞迴(Recursive)
    • 07.06-Defer, Panic & Recover
    • 07.07-Panic & Recover
    • 07.08-問題
  • 08-指標
    • 08.01-「*」與「&」運算符號
    • 08.02-new
    • 08.03-問題
  • 09-Struct 與 Interface
    • 09.01-struct
    • 09.02-Method
    • 09.03-Interface
    • 09.04-問題
  • 10-Concurrency(平行處理)
    • 10.01-Goroutine
    • 10.02-Channel
    • 10.03-問題
  • 11-Packages
    • 11.01-建立 Package
    • 11.02-文件
    • 11.03-問題
  • 12-測試
  • 13-The Core Packages
    • 13.01-字串
    • 13.02-輸入與輸出
    • 13.03-檔案與資料夾
    • 13.04-錯誤訊息
    • 13.05-Container 與 Sort
    • 13.06-雜湊&加解密
    • 13.07-伺服器
    • 13.08-解析命令列參數
    • 13.09-Synchronization Primitives(同步處理原始物件)
  • 14-下一步
    • 14.01-閱讀大師作品
    • 14.02-動手實作
    • 14.03-團隊合作
  • 15. 附錄-額外資源
Powered by GitBook
On this page
Edit on GitHub
  1. 07-函式

07.01-你的第二個函式

這是第6章的程式:

func main() {
    xs := []float64{98,93,77,82,83}
    
    total := 0.0
    for _, v := range xs {
        total += v
    }
    fmt.Println(total / float64(len(xs)))
}

這個程式計算一串數字的平均值,找出這類平均值是很常見的問題,所以比較理想的方式是將這段程式定義為函式。

average 函式需要使用一個 float64 型別的 slice,並能夠傳回 float64,我們在 main 函式前面增加這段程式碼:

func average(xs []float64) float64 {
    panic("Not Implemented")
}

函式的開頭是 func 關鍵字,後面跟著函式的名稱。函式的參數(輸入)可像這樣定義: name type, name type, …。我們這個函式有一個參數(一串分數),我們將它命名為 xs。在此參數之後的是傳回值的型別。函式的參數與傳回值型別則是所謂函式的特徵值(signature)。

最後,在大括號之間的函式的主體中會有一些陳述句,我們在函式的主體中呼叫一個內建的 panic 函式,這會產生一個執行期的錯誤訊息(本章稍後會再介紹 panic)。寫一個大函式可能會比較難,所以比較好的方式是將程式流程分成幾段比較好管理的小區塊,而不是直接寫成一大段程式碼。

現在我們將 main 函式中的一些程式碼搬到 average 函式中:

func average(xs []float64) float64 {    
    total := 0.0
    for _, v := range xs {
        total += v
    }
    return total / float64(len(xs))
}

要注意的是,我們將 fmt.Println 改成了 return,return 會讓函式立即停止,並將傳回值送給它的呼叫者,將 main 修改如下:

func main() {
    xs := []float64{98,93,77,82,83}
    fmt.Println(average(xs))
}

執行此程式應該會讓你得到與原本程式相同的結果,有些事要記得:

  • 參數的名稱不用與原本呼叫函式代入的變數名稱相同,例如下列方式:

func main() {
    someOtherName := []float64{98,93,77,82,83}
    fmt.Println(average(someOtherName))
}

而且我們的程式仍然可以運作。

  • 函式無法存取呼叫者的任何變數(除非透過指標),像下列的方式無法正常運作:

func f() {
    fmt.Println(x)
}
func main() {
    x := 5
    f()
}

我們也可以這樣寫:

func f(x int) {
    fmt.Println(x)
}
func main() {
    x := 5
    f(x)
}

譯者註:特別注意,func main() 中的 x 與 func f()中的 x ,雖然變數名稱相同,但是它們是分別屬於 main() 與 f() 的區域變數(local variable,或稱自動變數,auto variable),在main() 中的 x 變數之可視範圍(scope)僅限於 main() 函式中,而 f() 中的 x 變數可視範圍也僅限於 func() 函式中。

或是這樣:

var x int = 5
func f() {
    fmt.Println(x)
}
func main() {
    f()
}

函式是在堆疊(stack)中建立的,以下列的程式為例:

func main() {
    fmt.Println(f1())
}
func f1() int {
    return f2()
}
func f2() int {
    return 1
}

我們可以將上述的程式碼以具體的方式呈現如下:

我們每次呼叫函式時,我們就會將函式置入堆疊(push),而從函式返回時,則將函式從堆疊中移出(pop)。

我們也可以明確指定回傳值的資料型別與名稱:

  • func f2() (r int) {
        r = 1
        return
    }
Previous07-函式Next07.02-回傳多個值

Last updated 2 years ago