工作區與 GOPATH#

GOPATH 是 Go 的工作區路徑,決定原始碼、編譯產物與可執行檔的存放位置。

GOPATH 不能與 GOROOT(Go 安裝目錄)相同。GOPATH 可以包含多個路徑,類 Unix 系統用冒號分隔,Windows 用分號分隔。

工作區目錄結構#

GOPATH/
├── src/    # 原始碼目錄
├── pkg/    # 編譯後的套件歸檔檔案 (.a)
└── bin/    # 可執行檔案
  • src:所有 Go 原始碼。組織單位是「程式碼套件」(一個目錄對應一個套件)
  • pkg:編譯後的套件歸檔檔案(.a 檔案),按平台架構分(例如 linux_amd64darwin_arm64
  • bin:編譯後的可執行檔。把這個目錄加入 PATH 就能直接執行命令
套件匯入路徑範例

假設 GOPATH 為 /home/user/go

/home/user/go/
└── src/
    └── github.com/
        └── username/
            └── myproject/
                ├── main.go
                └── utils/
                    └── helper.go
  • myproject 的匯入路徑:github.com/username/myproject
  • utils 套件的匯入路徑:github.com/username/myproject/utils

原始碼檔案分類#

Go 的原始碼分三種:命令源碼檔案、程式庫源碼檔案、測試源碼檔案。

命令源碼檔案#

是 Go 程式的入口點:

  • 必須屬於 main 套件(package main
  • 必須包含無參數、無回傳值的 main 函式
package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}

同一個套件中不能同時存在多個命令源碼檔案。違反此規則,go buildgo run 會報錯。

接收命令列參數#

flag 套件處理命令列參數是 Go 的慣用做法:

package main

import (
    "flag"
    "fmt"
)

var name string

func init() {
    // 定義命令列參數
    flag.StringVar(&name, "name", "World", "使用者名稱")
}

func main() {
    // 解析命令列參數
    flag.Parse()
    fmt.Printf("Hello, %s!\n", name)
}
go run main.go -name="Go"
# 輸出: Hello, Go!
flag 套件常用函式
函式說明
flag.StringVar綁定字串型別參數到變數
flag.IntVar綁定整數型別參數到變數
flag.BoolVar綁定布林型別參數到變數
flag.Parse解析命令列參數
flag.Usage列印使用說明

程式庫源碼檔案#

封裝可重用的程式碼,供其他套件匯入:

// 檔案: utils/math.go
package utils

// Add 計算兩個整數的和(公開函式)
func Add(a, b int) int {
    return a + b
}

// multiply 計算兩個整數的積(私有函式)
func multiply(a, b int) int {
    return a * b
}

Go 透過識別字首字母的大小寫控制存取權限:

  • 首字母大寫:公開(可被其他套件存取)
  • 首字母小寫:私有(僅限當前套件)

internal 套件機制#

internal 目錄限制套件的可見範圍:

project/
├── internal/
│   └── secret/     # 僅 project 及其子套件可存取
│       └── config.go
└── main.go