iT邦幫忙

2023 iThome 鐵人賽

DAY 4
0
Modern Web

就是個Go,我也可以啦!GOGO系列 第 4

2023鐵人賽Day 4 Go的DRY藝術 - 使用套件

  • 分享至 

  • xImage
  •  

什麼是套件

在學習go之前我是一個ruby開發者,ruby有個我很喜歡的技術叫做NameSpace命名空間,這樣有助於程式碼隔離以及重複混入達到DRY,go也有命名空間,我們先來比較兩者的差異吧,ruby的命名空間使用module ,go的命名空間會使用package , 兩者的差異表格如下

功能/特點 Ruby (模块) Go (包)
定義 使用 module 關鍵字 使用 package 關鍵字
用途 提供命名空間、包裝方法、常量和類 提供命名空間、封裝代碼
導入方式 requirerequire_relative import
文件結構 通常一個模块對應一個 .rb 文件 一個包可以包含多個 .go 文件
訪問控制 模块本身不提供訪問控制,但模块内的常量、方法和類可以有 public, private, protected 限制 使用名稱首字母大小寫來控制可見性:大寫為公共,小寫為私有
巢狀命名空間 可以有巢狀模块 不直接支持,但可以通過子文件夾和子包來模擬
初始化 當模块被 require 時不保證會執行特定初始化代碼 init 函數,每個文件可以有多個,且在包被導入時自動執行
慣例 通常使用大駝峰命名法(例如:MyModule 使用小寫並且多個單詞之間使用下劃線(例如:mypackage

go 套件示例

├── go.mod
├── main.go
└── person
    ├── name.go
    └── verb.go
// go.mod
// go mod init gopratice 產生的
module gopratice

go 1.19

// main.go
package main

import (
	"fmt"

	"gopratice/person"
)

func main() {
	person.Name("John")
	person.Verb("running")
	fmt.Println("Done")
}

// person/name.go
package person

import "fmt"

func Name(p string) {
	fmt.Printf("Current person is: %+v\n", p)
}

// person/name.go
package person

import "fmt"

func Verb(v string) {
	fmt.Printf("Current verb is: %+v\n", v)
}

  • 從上面程式碼就會發現資料夾名稱(person)就是main.go所宣告的套件名稱,也就是一個套件實際上是系統中的一個根目錄
  • 在Go中,一個套件實際上與文件系統中的一個根目錄相對應,這個目錄下的所有Go源文件都被編譯為同一個套件。透過這種結構,能夠使代碼更有組織並促進模組化開發。
  • 在name.go 及 verb.go內我使用 大寫的funcrtion名稱 Name/Verb 是因為我要讓引入這個person套件的地方使用這兩個function,go沒有 public, private, protected 等控制去控制存取,go是使用名稱首字母大小寫來控制可見性:大寫為公共,小寫為私有

管理套件 GO Module

模組(module)在 Go 語言中是一個重要的概念,一個模組是相關套件的集合,並且包括一個 go.mod 文件,其中定義了模組的路徑和依賴關係

在專案的根目錄輸入

go mod init [模組名稱]

以上面示例為例 go mod init gopratice

若你有加入程式或移除套件時,應於terminal下指令重整go.mod

go mod tidy

若要下載第三放套件可以使用下方語法

go get <package>@<version>

你可以使用上述命令显式地升級或降級一個套件到指定的版本。

模組與套件路徑

  • 儲存庫路徑是指向某個 VCS(版本控制系統)儲存庫的 URI。在 Go 模組中,這個路徑是模組路徑的前綴,通常與 Git、Mercurial 等儲存庫的 URL 對應。例如,github.com/username/projectname 就是一個儲存庫路徑

以下的路徑指向模組中的特定套件:

  • 模組路徑:github.com/username/projectname
  • 套件路徑:github.com/username/projectname/mypackage

套件的呼叫與執行

go 可以讓你為套件取別名

import <別名> <套件>

以下例子

package main 

import (
  f "fmt"
)

func main() {
  f.Println("hello")
}

可執行與不可執行

Go 程式是透過套件來組織的。package <pkgName> 這一行告訴我們當前檔案屬於哪個套件

可執行的套件有兩個特徵

  • 一個聲明為main()函數,建構程序在構建可執行文件時,需要找到已經聲明的main函數,把他作為程序的入口
  • 第一行有一個名為main的package package main

如果main函式不在main裡,構建函式就不會生成可執行的文件

而套件名 main 則告訴我們它是一個可獨立執行的套件,它在編譯後會產生可執行檔案

init()

任何套件,都可以定義一個函式叫 init()

package main

import (
  "fmt"
)

func init() {
  fmt.Println("hello world")
}

func main() {
  fmt.Println("main 函式")
}

這個執行的順序為

  1. 初始化外部套件:首先,程式會初始化任何外部依賴的套件。這些套件可能包括標準庫的套件以及第三方庫。
  2. 初始化套件自身:接下來,程式會初始化當前套件的變數和常數。這可能涉及執行一些計算或調用函數來設置變數的初始值。
  3. 執行外部套件的 init():如果外部套件中有 init 函數,它們會按照引入的順序執行。每個套件可能有多個 init 函數,它們會按照在代碼中出現的順序執行。
  4. 執行套件的 init():接下來,程式會執行當前套件的 init 函數(如果有的話)。與外部套件一樣,這些函數會按照在代碼中的順序執行。
  5. 執行 main 套件的 main():最後,程式進入其主要的執行階段,執行 main 套件中的 main 函數。這個函數是程式的入口點,並包括程式的主要邏輯。

參考書籍

The Go Workshop 完全自學Go語言


上一篇
2023鐵人賽Day 3 Go怎麼傳值,先讀懂指標-2
下一篇
2023鐵人賽Day 5 Go X 方法
系列文
就是個Go,我也可以啦!GOGO30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言