iT邦幫忙

2023 iThome 鐵人賽

DAY 11
0
自我挑戰組

Go in 3o系列 第 11

[Day11] Go in 30 - 函式- 簡介

  • 分享至 

  • xImage
  •  

一、本篇提要

從這篇開始,將進入到函式的介紹,將會知道它的組成、函式的變數範圍、如何建立(參數不定函式、匿名函式、閉包(closure))、呼叫函式,或將函示當成參數和回傳值來使用,並用defer來延遲函式執行。

今天主題簡單羅列一下 :

  • 函式簡介
  • 函式的宣告與組成
  • 呼叫函式
  • 參數與回傳值
  • naked return

二、函式簡介

函式其實就是我們宣告來從事一項任務的程式碼,Go語言函式可以完全沒有輸入和輸出,也可以有多重輸入和輸出。而Go 和其他程式語言不同之處在於---可以回傳多重值

以下羅列Go語言和其他與眾不同的特性 :

  1. 將函式當成引數傳給其他函式
  2. 將函式賦值變數、以及當成另一個函式傳回值
  3. 將函式視為型別
  4. 匿名函式(annoymous)和閉包(closure)函式

Go 語言是一級函式(first-class functions),也就是函式可以當成其他函式的引數或傳回值,而可以接收其他函式為引數的函式又稱為高階函式(higher-order functions)。

函式的用途不外乎 :

  1. 分解複雜的問題,將一大問題拆解成幾塊小任務。
  2. 精簡程式碼,將重複的程式碼獨立出來。
  3. 重複使用性,一個共同功能可供其他人呼叫。
  4. 單一責任制,一個函式應當只負責一個任務。
  5. 短小精悍

三、函式的宣告與組成

宣告函式典型結構 :

func add(i, j int) int {
//程式碼
}
  • 函式宣告 : 以關鍵字func開頭,可以在任何層級宣告。

  • 函式識別名稱(identifier) : 即函式名稱,習慣以駝峰式(camelCase),名稱要有意義,也可以沒名稱(匿名函式)後續介紹。

  • 參數清單 : parameter,函式的輸入值

<名稱1> <型別1>, <名稱2> <型別2>.....

如果型別一樣,可以用簡寫法 :

<名稱1>, <名稱2> <型別>.....
  • 傳回型別 : 就是傳回的型別,可以是bool、string、map 或是另一個函式或沒有回傳值,而Go比較特殊的是他可以傳多重值。

  • 函式特徵 : 函式特徵是一個術語,它是函式的輸入值與輸出值得合稱。

三、呼叫函式

定義好一個函式,但卻不執行它,當然不會有效果,如果要執行函式就以其名稱呼叫 :

函式名稱(參數1, 參數2...)

範例 :

package main

import "fmt"

// 定義一個名為add的函數,接收兩個整數參數,傳回它們的和
func add(x, y int) int {
     return x + y
}

func main() {
     // 呼叫add函數,並將傳回值賦給result變數
     result := add(5, 3)   
     // 列印結果
     fmt.Println("5 + 3 =", result)
}

上面的程式碼定義了一個名為add的函式,該函式接收兩個整數參數x和y,並傳回它們的和。 在main()中,我們呼叫add函式並將傳回的結果儲存在result變數中,然後列印出結果。 這是一個非常簡單的函式範例,用於演示如何定義和呼叫函式。

三、參數與回傳值

3.1 接收多重回傳值

值1 , 值2... := 函式名稱()

範例如下 :

package main

import "fmt"

// 定義一個名為divide的函數,接收兩個整數參數,傳回它們的商和餘數
func divide(x, y int) (int, int) {
     quotient := x / y
     remainder := x % y
     return quotient, remainder
}

func main() {
     // 呼叫divide函數,並接收傳回的兩個值
     q, r := divide(10, 3)
    
     // 列印商和餘數
     fmt.Println("商:", q)
     fmt.Println("餘數:", r)
}

在上面的程式碼中,我們定義了一個名為divide的函式,該函式接收兩個整數參數x和y,並傳回它們的商和餘數。 在main函式中,我們呼叫divide函式,並使用q和r兩個變數接收傳回的兩個值,然後列印出商和餘數。這是一個接收多重回傳值的範例。

下一篇會介紹到如何在函式體內執行所謂 naked return, 即不在return指名傳回值做法。

3.2 忽略一部分回傳值

Go語言允許你忽略回傳值,上一個除法函式範例divide會回傳商與餘數,但我只需要商,想要忽略餘數,在不考慮直接回傳商數就好得情況下,我們可以使用底線(_),對! 就是底線(blank identifier)來忽略該回傳值 :

package main

import "fmt"

// 定義一個名為divide的函數,接收兩個整數參數,傳回它們的商和餘數
func divide(x, y int) (int, int) {
     quotient := x / y
     remainder := x % y
     return quotient, remainder
}

func main() {
     // 呼叫divide函數,但使用底線來忽略餘數
     q, _ := divide(10, 3)
    
     // 列印商,不關心餘數
     fmt.Println("商:", q)
}

Note 很多Go函式都會以error為第二回傳值,這也是設計Go函式應該要遵循的慣例。對於可能會回傳error的函示,最好別忽略errorc回傳值,之後有篇章會介紹~

3.3 naked return

在Go語言中,naked return 是一種特性,它允許在函式體內直接使用 return 關鍵字,而不會指定特定的回傳值。 這在一些情況下可以提高程式碼的可讀性。

通常,我們在函式中使用 return 語句時需要明確指定傳回的值,例如:

func add(a, b int) int {
     result := a + b
     return result
}

但是,如果函式的回傳值已經在函式的參數清單中進行了命名,你可以使用 naked return 來簡化程式碼,如下所示:

func add(a, b int) (result int) {
     result = a + b
     return
}

在這個範例中,我們將傳回值 result 在函式參數清單中聲明,並在函式體內直接使用 return 關鍵字,而不需要再次指定 return result。 Go 會自動將 result 的值傳回為回傳值。

需要注意以下幾點關於 naked return 的使用:

  1. naked return 主要用於簡化程式碼,增強可讀性。 它不適用於所有情況,只有當返回值在函數參數清單中已經明確定義時才能使用,尤其在很長的函式中,會造成可讀性差。

  2. 如果函數體內存在多個返回值變量,naked return 會變得複雜且難以理解,因此建議在適當的情況下使用 naked return。

  3. naked return 不會影響函數的效能,編譯器會對其進行最佳化,所以不必擔心效能問題。

以上就是有關函式的第一篇~~~Thx


上一篇
[Day10] Go in 30 - 空介面與型別檢查
下一篇
[Day13] Go in 30 - 函式 - 參數不定函式、匿名函式與閉包
系列文
Go in 3o30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言