iT邦幫忙

2023 iThome 鐵人賽

DAY 23
0
自我挑戰組

Go in 3o系列 第 23

[Day23] Go in 30 - 套件(package) - 簡介

  • 分享至 

  • xImage
  •  

一、本篇提要

本篇要示範的是,Go語言運用套件的重要性,並說明如何讓程式更好維護、更有組織等,在這個主題之下將理解,套件如何定義、套件內名稱匯出方式、替套件建立別名、Go Modules概念及Go get 匯入自訂或第三方套件。

  • 什麼是套件
  • 套件管理

二、什麼是套件 ?

在程式設計中,套件 (或 package) 指的是一組功能相關的程式碼,被組織在一起,以便於模組化、重用和維護。
在Go中,套件是多個 .go 檔案的集合,這些檔案位於相同的目錄下並有一個共同的 package 定義。Go的套件機制提供了程式碼的模組化和封裝。

套件的好處,在於開發出 好維護、可重複利用、模組化。

2.1 使用套件

Don't Repeat yourself, DRY

Go 語言遵循 DRY 法則,即不應重複相同的程式碼。DRY 的初衷是將程式碼重構成函式,但當我們有成千上萬的函式該怎麼辦?

Go 語言允許讓你好幾個檔案共用一個套件,意思就是可以將一個套件拆成好幾個更好維護的小單元,而每個檔案都應該以該單元的功能來命名,Go語言並不在意套件中含有多少個檔案,只要同一個資料夾中的檔案都宣告為某某套件,他們就可以透過該套件存取。

如下,我們有一個string目錄,目錄底下又有多個 .go 檔案。

strings
    builder.go
    compare.go
    reader.go
    replace.go
    search.go
    string.go
    ...

2.2 套件命名

名稱代表這個套件的內容、用途,十分重要。

應該符合:

  • 全小寫
  • 簡潔
  • 使用非複數名詞(能免則免)
  • 避免太通用的名稱

例如 :

strconv (string conversion, 字串轉換)
regexp (regular expression, 正規表達式)
sync (synchronization, 同步運算)
os (operation system, 作業系統)

2.3 套件宣告

就是我們很常見到的 :

package <套件名稱>

就上述所說strings套件,當中所有檔案都是以 package strings 開頭,代表他們屬於strings套件。

2.4 將套件的功能匯出(exported)

在Go語言中,只有被匯出(exported)的套件變數、常數、型別、函式等能被套件外的程式存取;未匯出(unexported)的只限套件內使用。

如何判斷有無匯出 ? 很簡單

以英文大寫字母開頭,的東西就是可以被外部訪問,反之就不行,Go沒有所謂存取修飾符(access modifier)
例如: Java 中的 private 和 public 關鍵字。
對此,我們應該只匯出必要功能,不必要的應該隱藏起來。

補充說明 :
字首大寫,更精確地來說應該是 Unicode 大寫字元,來判斷該功能有沒有匯出。

三、管理套件

這邊會說明另一個重要的觀念----理解 Go 編譯器會去哪裡尋找我們應用程式所引用的套件。
ps. 1.11版後,Go Modules 取代了$GOPATH

  • GOROOT
  • GOPATH
  • GO Modules

3.1 GOROOT

Go編譯器必須知道怎麼找到我們引用 import 匯入的套件的原始檔,編譯器會利用環境變數 $GOROOT 去尋找他們,所謂 $GOROOT 就是你 Go 在你電腦的安裝路徑,若要檢視可以輸入指令: go env

會看到一連串環境變數 :
https://ithelp.ithome.com.tw/upload/images/20231004/20162693l6TDhd71qi.png

3.2 GOPATH

$GOPATH 通常指向使用者的家目錄(home directory),例如在 Windows 中可能是 "C:\Users\使用者名稱\go"。而 $GOPATH 下會有三個子目錄:bin、pkg 和 src。

  • 目錄 bin 用途,當我們執行 go install 時,Go 語言會把編譯好的二進制執行檔放在這裡。
  • 目錄 pkg 除了放編譯過的套件,也會於其mod子資料夾下存放你用 go get 下載的第三方套件(等等說明),
  • 1.11版前,使用者所有專案及套件都置於 $GOPATH\src\目錄下,但1.11後,新的 Go Modules 功能解除了這個限制**

3.3 Go Modules

Go Modules 是為了取代 GOPATH 而生,其中 "modules" 代表了一系列的套件集合。透過模組路徑 (modules path) ,Go 能確切地找到你的套件。,這麼一來就不用依賴GOPATH來放置套件 :

如果你有使用到自訂或是外部套件,你必須再專案的根目錄建立一個 go.mod 檔案,辦法是輸入以下指令:

go mod init <模組名稱>

至於模組名稱,他不需要跟專案名稱或是專案資料夾同名,而且實際上可能寫成像是(example.com/mymodule)之形式。

當我們對程式加入或是移除套件時,我們應該要在專案目錄下輸入以下指令,好重整go.mod的內容:

go mod tidy

Go Modules 其實不只能用來尋找套件,它也能用於套件的版本控管 官方文件

四、補充說明 GO111MODULE 環境變數

我們可以使用 GO111MODULE 環境變數 (和GOROOT、GOPATH一樣可以透過 go env 觀看) 來控制 Go Module 有沒有啟用 :

https://ithelp.ithome.com.tw/upload/images/20231004/20162693cuw5k4htCf.png

五、練習-建立一個計算形狀面積的套件

專案名為Project1,即將打造的目錄結構 :

https://ithelp.ithome.com.tw/upload/images/20231004/20162693ChZjKA5ddx.png

5.1 shape 套件

package shape

import (
	"fmt"
)

type Shape interface {
	area() float64
	name() string
}

type Triangle struct {
	Base float64
	Height float64
}

type Rectangle struct {
	Length float64
	Width float64
}

type Square struct {
	Side float64
}

func PrintShapeDetails(shapes ...Shape) {
	for _, item := range shapes {
		fmt.Printf("%s的面積: %.2f\n", item.name(), item.area())
	}
}

func (t Triangle) area() float64 {
	return (t.Base * t.Height) / 2
}

func (t Triangle) name() string {
	return "三角形"
}

func (t Rectangle) area() float64 {
	return t.Length * t.Width
}

func (t Rectangle) name() string {
	return "長方形"
}

func (t Square) area() float64 {
	return t.Side * t.Side
}

func (t Square) name() string {
	return "正方形"
}

5.2 建立 go.mod

https://ithelp.ithome.com.tw/upload/images/20231004/201626930a83U3S1nR.png

會提示你要不要用 go mod tidy 重整 go.mod

現在,資料夾 project01 就會出現一個 go.mod 檔案。

5.3 建立main套件

package main

import (
	"project/src/project01/shape"
)

func main() {
    t := shape.Triangle{Base:18.2, Height:30.2}
    r := shape.Rectangle{Length: 20, Width: 23.3}
    s := shape.Square{Side: 100}
    shape.PrintShapeDetails(t, r, s)
}

輸出結果 :
https://ithelp.ithome.com.tw/upload/images/20231004/20162693AYBpdGGJGQ.png

接下來要將main編譯成一個可執行的二進位檔(要在/main的目錄),
步驟也就是將檔案產生二進制檔--->編譯為可執行文件exe檔--->運行exe。

https://ithelp.ithome.com.tw/upload/images/20231004/20162693IRobC76Czb.png

此時我們可以看到該目錄下多了一個exe檔:

https://ithelp.ithome.com.tw/upload/images/20231004/201626931kzahecLTT.png

執行這個exe檔 :

https://ithelp.ithome.com.tw/upload/images/20231004/201626939VfeyvqiQw.png

當然也可以直接用指令 :

go run main.go

會比上面的慢。但原理一樣,轉為二進制寫在go run底層在執行。

https://ithelp.ithome.com.tw/upload/images/20231004/20162693J6f2GgkOIj.png

以上就是 golang 套件 Part 1 有關定義、匯出、組織結構的介紹,接下來是go get 取得與使用第三方模組或套件。


上一篇
[Day22] - Go in 30 - 泛型(generic)
下一篇
[Day24] Go in 30 - 套件(package) - 第三方模組或套件
系列文
Go in 3o30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言