iT邦幫忙

2024 iThome 鐵人賽

DAY 22
1
Modern Web

Go 快 Go 高效: 從基礎語法到現代Web應用開發系列 第 22

【Day22】Go 檔案傳送 | I/O 操作介紹 | BONUS : Go - Native 工具介紹

  • 分享至 

  • xImage
  •  

概述

本篇文章主要是教大家如何在 Golang 上處理檔案上傳的操作,那我們的主題會圍繞在 ioos 這兩個 package 的介紹。


基本上傳

package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func uploadFile(w http.ResponseWriter, r *http.Request) {
	file, header, err := r.FormFile("file")
	if err != nil {
		fmt.Fprintf(w, "Failed to get file: %v", err)
		return
	}
	defer file.Close()

	dstPath := "/path/to/destination/" + header.Filename
	dst, err := os.Create(dstPath) // 建立目標檔案
	if err != nil {
		fmt.Fprintf(w, "Failed to create file: %v", err)
		return
	}
	defer dst.Close()

	// 使用 io.Copy 將上傳的檔案寫入到目標文件中
	if _, err := io.Copy(dst, file); err != nil {
		fmt.Fprintf(w, "Failed to write file: %v", err)
		return
	}

	fmt.Fprintf(w, "File uploaded successfully!\n")

	// 開啟剛剛上傳的文件進行讀取
	openedFile, err := os.Open(dstPath)
	if err != nil {
		fmt.Fprintf(w, "Failed to open file after upload: %v", err)
		return
	}
	defer openedFile.Close()

	// 讀取並顯示文件內容
	fileContent := make([]byte, 1024)
	n, err := openedFile.Read(fileContent)
	if err != nil && err != io.EOF {
		fmt.Fprintf(w, "Failed to read file: %v", err)
		return
	}

	fmt.Fprintf(w, "Uploaded file content (first %d bytes): %s", n, string(fileContent[:n]))
}

func main() {
	http.HandleFunc("/upload", uploadFile)
	http.ListenAndServe(":8080", nil)
}
  • 接收上傳的文件:使用 r.FormFile("file") 來讀取上傳的檔案,file 是上傳文件的 Readerheader 是文件的元數據,所以如果我們要測試 api 就需要在 "key" 輸入 file 然後 "類型"記得選擇file
  • os.Create() 用來創建一個新的文件。如果文件已經存在,則會覆蓋該文件。這個函數返回一個 *os.File,代表新創建的文件對象。程式中的 dst 是創建的目標文件,並用於接收上傳的數據。
  • io.Copy() 是 Go 中常見的 I/O 操作,用來將數據從一個 Reader 複製到一個 Writer。在這個例子中,它將從上傳的文件(file,是 multipart.File 類型,實現了 Reader 接口)讀取數據,並寫入到目標文件(dst,實現了 Writer 接口)。這樣可以快速地將整個文件內容複製到本地。
  • os.Open() 是用來打開一個現有的文件。它返回一個指向該文件的 *os.File,用於進行讀取操作。在這裡,我們打開剛剛上傳並保存的文件,來檢查文件的內容是否正確。
  • Read() 是從打開的文件中讀取數據,這裡將文件內容讀取到一個 byte 切片中。在這個範例中,我們最多讀取 1024 byte的內容。Read() 返回的 n 是實際讀取到的byte數。如果文件比較小,可能不會讀滿 1024 字節。當讀到文件末尾時,Read() 會返回 io.EOF 錯誤,表示文件已經讀取完畢。

API測試

我這裡選擇在我的/Users/imac/Documents/路徑下去做上傳的動作

Postman

https://ithelp.ithome.com.tw/upload/images/20240929/20161850Msi3LXCire.png

Apifox

https://ithelp.ithome.com.tw/upload/images/20240929/20161850yPIxdYgaS2.png

仔細看修改日期的話會發現我第二次上傳時會對原有的檔案做複寫的動作!


實時處理數據

使用管道(Pipe)來進行流式操作,這在處理大文件或需要實時處理數據的場景中特別有用。io.Pipe() 允許在同一個程式中創建一個讀寫管道,一邊寫入,一邊可以即時讀取。

package main

import (
    "fmt"
    "io"
    "os"
    "net/http"
)

// 處理上傳過程中的數據
func processData(r io.Reader, w io.Writer) {
    buffer := make([]byte, 1024)
    for {
        n, err := r.Read(buffer)
        if err != nil && err != io.EOF {
            fmt.Println("Error while reading:", err)
            return
        }
        if n == 0 {
            break
        }
        // 在這裡可以處理讀取的數據,例如進行加密或壓縮
        // 現在只是將原始數據寫回去
        if _, err := w.Write(buffer[:n]); err != nil {
            fmt.Println("Error while writing:", err)
            return
        }
    }
}

func uploadFile(w http.ResponseWriter, r *http.Request) {
    file, header, err := r.FormFile("file")
    if err != nil {
        fmt.Fprintf(w, "Failed to get file: %v", err)
        return
    }
    defer file.Close()

    dst, err := os.Create("/path/to/destination/" + header.Filename)
    if err != nil {
        fmt.Fprintf(w, "Failed to create file: %v", err)
        return
    }
    defer dst.Close()

    // 使用 io.Pipe() 建立讀寫管道
    reader, writer := io.Pipe()

    // 使用 Goroutine 實時處理數據
    go func() {
        defer writer.Close() // 確保寫入端最後會關閉
        processData(file, writer)
    }()

    // 使用 io.Copy 將處理後的數據寫入目標文件
    if _, err := io.Copy(dst, reader); err != nil {
        fmt.Fprintf(w, "Failed to copy data: %v", err)
        return
    }

    fmt.Fprintf(w, "File uploaded and processed successfully!")
}

func main() {
    http.HandleFunc("/upload", uploadFile)
    http.ListenAndServe(":8080", nil)
}
  1. processData 函數:
    • 使用 r.Read(buffer) 讀取數據到緩衝區(buffer),每次讀取最多 1024 字節。
    • 檢查是否讀取完成,若讀取完成則跳出循環。
    • 使用 w.Write(buffer[:n]) 將讀取到的數據寫入到管道的另一端。
    • 這裡的 r 是上傳的文件,w 是 io.PipeWriter,這樣通過管道把數據傳送到目標文件。
  2. uploadFile 函數:
    • 使用 io.Pipe() 創建了一個連接的 PipeReaderPipeWriter,使得數據可以在不同的 Goroutine 之間進行傳輸。這裡的 readerwriter 對應於這個管道的兩端。
    • Goroutine 實時處理上傳的文件,並將處理後的數據傳給管道的讀取端(reader),然後將這些數據複製到目標文件中。
    • 這裡 io.Copy(dst, reader) 的作用是從管道的讀取端讀取數據,並寫入到目標文件(dst)中。dst 是一個打開的文件句柄,reader 是通過 io.Pipe() 創建的管道讀取端。這樣的設計可以實現流式的處理數據,無需將整個文件都讀到內存中,可以有效處理大文件。

大型檔案處理

package main

import (
    "fmt"
    "io"
    "os"
    "sync"
)

const (
    chunkSize       = 5 * 1024 * 1024 // 每個切片大小為 5MB
    maxGoroutines   = 6               // 限制同時運行的 Goroutine 數量
    largeFilePath   = "/path/to/fileName" // 替換為實際的檔案路徑
    chunkFilePrefix = "largefile_part_"    // 切片檔案的前綴名
)

// uploadFileInChunks 將大檔案切成小片段並並發地處理
func uploadFileInChunks(file *os.File, filename string) error {
    // 取得檔案大小
    fileInfo, err := file.Stat()
    if err != nil {
        return fmt.Errorf("failed to get file info: %v", err)
    }
    fileSize := fileInfo.Size()

    // 計算總的切片數量
    totalChunks := int((fileSize + chunkSize - 1) / chunkSize)
    fmt.Printf("Total chunks to process: %d\n", totalChunks)

    // 設置同步機制和錯誤通道
    var wg sync.WaitGroup
    semaphore := make(chan struct{}, maxGoroutines) // 控制並發數量
    errorCh := make(chan error, totalChunks)        // 錯誤通道

    // 啟動 Goroutine 處理每個切片:
    	for chunkNumber := 0; chunkNumber < totalChunks; chunkNumber++ {
		wg.Add(1)
		semaphore <- struct{}{} // 佔用一個信號量
		go func(chunkNum int) {
			defer wg.Done()
			defer func() { <-semaphore }() // 釋放信號量

			offset := int64(chunkNum) * chunkSize
			remaining := fileSize - offset
			currentChunkSize := chunkSize
			if remaining < chunkSize {
				currentChunkSize = int(remaining)
			}

			// 創建切片檔案
			chunkFileName := fmt.Sprintf("%s%d", chunkFilePrefix, chunkNum)
			chunkFile, err := os.Create(chunkFileName)
			if err != nil {
				errorCh <- fmt.Errorf("failed to create chunk file %s: %v", chunkFileName, err)
				return
			}

			// 確保檔案被正確關閉
			defer func() {
				if err := chunkFile.Close(); err != nil {
					fmt.Printf("failed to close chunk file %s: %v\n", chunkFileName, err)
				}
			}()

			// 讀取指定區段的資料
			buffer := make([]byte, currentChunkSize)
			_, err = file.ReadAt(buffer, offset)
			if err != nil && err != io.EOF {
				errorCh <- fmt.Errorf("failed to read chunk %d: %v", chunkNum, err)
				return
			}

			// 將資料寫入切片檔案
			_, err = chunkFile.Write(buffer)
			if err != nil {
				errorCh <- fmt.Errorf("failed to write to chunk file %s: %v", chunkFileName, err)
				return
			}

			// 上傳切片到伺服器
            // 自定義上傳操作(因為程式太長了所以沒加上)

			fmt.Printf("Chunk %s uploaded successfully!\n", chunkFileName)

			// 刪除切片檔案以節省空間
			err = os.Remove(chunkFileName)
			if err != nil {
				fmt.Printf("Warning: failed to delete chunk file %s: %v\n", chunkFileName, err)
			} else {
				fmt.Printf("Chunk file %s deleted successfully.\n", chunkFileName)
			}
		}(chunkNumber)
	}

    // 等待所有 Goroutine 完成
    wg.Wait()
    close(errorCh)

    // 檢查是否有錯誤發生
    var finalErr error
    for err := range errorCh {
        if finalErr == nil {
            finalErr = err
        } else {
            finalErr = fmt.Errorf("%v; %v", finalErr, err)
        }
    }

    return finalErr
}

func main() {
    // 打開大檔案
    file, err := os.Open(largeFilePath)
    if err != nil {
        fmt.Printf("Failed to open file: %v\n", err)
        return
    }
    defer func() {
        if err := file.Close(); err != nil {
            fmt.Printf("Failed to close file: %v\n", err)
        }
    }()

    // 將檔案切成小塊並進行並發處理
    if err := uploadFileInChunks(file, "largefile"); err != nil {
        fmt.Printf("Error: %v\n", err)
    } else {
        fmt.Println("All chunks processed successfully!")
    }
}
  • 透過 file.Stat() 取得檔案大小,並計算總共需要切割的片段數量。
  • semaphore 是一個有緩衝的 channel,用來限制同時運行的 Goroutine 數量。
  • errorCh 用於收集所有 Goroutine 中發生的錯誤。
    對每個切片:
  • 計算切片的讀取偏移量和大小,確保最後一個切片的大小正確,避免讀取超出檔案末尾。
  • 讀取檔案的指定區段並寫入切片檔案,使用 ReadAt 方法在指定偏移量讀取資料,避免多個 Goroutine 互相干擾。
  • 自定義方法將切片上傳到伺服器。
  • 上傳成功後,刪除本地的切片檔案(可選),呼叫 os.Remove 刪除該切片檔案。

總結

本文介紹了在 Golang 中使用 ioos 套件實現檔案上傳的多種方法。首先,通過基本上傳範例展示了如何接收並保存上傳的檔案。接著,介紹了使用管道(io.Pipe)進行實時數據處理,適用於大檔案或需要即時處理的場景。最後,深入探討了大型檔案的處理策略,包括將檔案切割成小片段、利用 Goroutine 進行並發上傳,以及在成功上傳後自動刪除切片檔案以節省空間。通過這些方法,開發者可以構建高效、穩定的檔案上傳系統,滿足各種應用需求。


BONUS:Go - Native Tool 介紹

由於一開始我心血來潮介紹的IDE是GoLand,因為太方便了幾乎用內建的功能就能概括所有案例,所以忘記提到 Golang 的原生工具/images/emoticon/emoticon13.gif,因此用VSCode開發的可能會有些不明白,先說個Sorry/images/emoticon/emoticon16.gif

工具 描述 使用案例
go build 將 Go 代碼編譯為可執行檔 建立獨立的程式
go install 編譯並安裝 Go 套件 讓套件可以在其他專案中使用
go clean 移除編譯過程中的遺留檔案 清理專案目錄
go fmt 格式化 Go 代碼以保持一致性 維持整潔的程式碼風格
go get 匯入模組相依性 管理模組內的依賴 (從 Go 1.22 起)
go mod download 下載專案相依性 管理編譯所需的依賴
go mod tidy 整理和清理相依性 避免相依性衝突
go mod verify 驗證 go.mod 中列出的相依性 確保依賴可下載並完整
go mod vendor 建立一個本地 'vendor' 資料夾,複製所有依賴 本地存儲所有依賴
go run 直接編譯並執行 Go 代碼 快速測試而無需建立可執行檔
go test 執行單元測試 自動化代碼測試
go vet 分析 Go 代碼中的問題 提早發現潛在錯誤
go link 鏈接套件以建立自定義編譯 進階編譯工作流程
go doc 探索 Go 套件文件 查詢函式和型態的相關資訊
go version 檢查已安裝的 Go 版本 確保相容性

Go 構建工具

  • go build
    go build 命令簡潔有力,能將你的 Go 原始碼轉換成自包含的可執行二進位檔,以便隨時執行。

主要特點

  • 輕鬆編譯:無需處理複雜的專案配置或外部構建系統,go build 會智能分析你的 Go 代碼及其依賴。
  • 跨平台能力:通過設置 GOOSGOARCH 環境變量,輕鬆生成適用於不同操作系統和架構(如 Linux、Windows、macOS、ARM)的可執行檔。
  • 自訂化:控制輸出檔名,管理優化的構建標誌,並使用額外選項將靜態資源嵌入二進位檔中。
# 從當前套件構建可執行檔
go build

# 為 Linux AMD64 架構構建
GOOS=linux GOARCH=amd64 go build

使用時機

  • 部署:準備獨立運行的 Go 應用程式於目標系統上。
  • 分發:讓他人使用你的 Go 軟體,而無需他們擁有 Go 開發環境。
  • go install

go install 是 go build 的好夥伴,能無縫地編譯並安裝 Go 套件或命令至你的 Go 工作區,並允許你指定版本以管理專案的相容性。

主要特點

  • 套件安裝:下載並安裝第三方 Go 套件,讓其代碼在專案中可用。
  • 命令創建:編譯用 Go 編寫的命令行工具,並將生成的可執行檔放置在 $GOPATH/bin 目錄中。
  • 依賴管理:自動處理安裝套件或命令的依賴關係。
  • 開發效率:安裝常用的 Go 命令或本地套件,方便存取。
# 安裝 'goreleaser' 套件(發布自動化工具)
go install github.com/goreleaser/goreleaser@latest

# 檢查是否正確安裝
goreleaser --help

使用時機

  • 下載外部套件:讓專案輕鬆使用外部 Go 套件。
  • 編譯命令行工具:將自製的 Go 命令行工具添加至 $GOPATH/bin,方便執行。
  • go clean

go clean 是用來清理 Go 專案目錄的工具,能智能地移除建構過程中產生的物件檔、暫存檔及其他雜項檔案。

主要特點

  • 工作區清潔:保持專案目錄整潔,便於導航和管理代碼。
  • 構建優化:減少編譯器的工作量,潛在提升大型專案的構建時間。
  • 全新開始:在重大構建或排除編譯問題前,確保有一個乾淨的環境。
# 清理當前專案目錄
go clean

# 清理並移除整個 Go 構建快取
go clean -cache

# 顯示將要清理的內容,但不實際移除
go clean -n

使用時機

  • 定期清理:作為日常開發流程的一部分,保持專案結構整潔。
  • 分發前:準備精簡的專案檔案以供分享或部署。
  • 排除故障:面對意外的構建錯誤時,使用 go clean 可能解決由於過時的建構工件所引起的問題。
  • go fmt

go fmt(以及其伴隨的 gofmt)提供了統一可讀且易於維護的 Go 代碼基礎。它會自動根據官方的 Go 樣式指南重新格式化你的 Go 原始碼。

主要特點

  • 統一性:確保所有 Go 代碼無論作者為誰,都遵循一致的空格、縮排和格式。
  • 可讀性:使 Go 代碼更易讀、易理解,促進團隊合作。
  • 專注邏輯:省去花在代碼樣式上的時間,讓開發者能專注於核心功能。
# 格式化當前目錄中的檔案
go fmt

# 格式化當前目錄及子目錄中的所有 Go 檔案
go fmt ./...

# 檢查檔案是否已格式化,且不進行修改
gofmt -l ./...

使用時機

  • 隨時使用:將 go fmt 整合到開發流程中。許多代碼編輯器和 IDE 可自動在保存時執行。
  • 提交前:考慮將 go fmt 設為提交鉤子,確保團隊內的代碼一致性。
  • 舊專案:對舊有的 Go 代碼進行格式化,立即提升可讀性。
  • go get

go get 命令過去用於下載和安裝套件,但自 Go 1.17 起,其功能有所變更:

主要變更

  • Go 1.17 以後:安裝可執行檔已被棄用,改用 go install
  • Go 1.18 及更高版本:在使用 Go 模組時,go get 主要用於管理 go.mod 文件中的依賴。
  • Go 1.22 以後:在使用 Go 模組時,go get 只管理模組內的依賴,且在 GOPATH 模式下已被棄用。
# 下載並更新所有對應的套件
go get

# 下載 'github.com/sirupsen/logrus' 日誌套件
go get github.com/sirupsen/logrus

Go 模組管理工具

  • go mod download

go mod download 是 Go 模組依賴管理系統的重要組成部分,負責下載專案 go.modgo.sum 文件中定義的依賴版本。

主要特點

  • 模組解析:抓取所需的模組及其依賴,並存儲在模組快取中(通常位於 $GOPATH/pkg/mod)。
  • 離線構建:依賴下載後,本地即可使用,無需持續的網路連接。
  • 版本一致性:與 go.modgo.sum 協同工作,確保使用指定的依賴版本進行可預測的構建。
# 下載當前模組的依賴
go mod download

# 下載特定模組的依賴(適用於多模組設置)
go mod download github.com/some/module

使用時機

  • 初始化:在初始化新 Go 模組或修改 go.mod 文件後使用。
  • 構建前:在執行 go build 前,確保所有必要的依賴已就緒。
  • go mod tidy

go mod tidy 是 Go 模組系統中的維護助手,幫助保持專案依賴結構的清潔和一致。

主要特點

  • 模組維護:確保 go.mod 文件準確反映實際使用的依賴。
  • 移除過時依賴:識別並移除 go.modgo.sum 文件中未使用的模組條目。
  • 依賴更新:抓取缺失的模組並更新現有依賴至最低必要版本。
# 整理當前專案的模組依賴
go mod tidy

使用時機

  • 定期使用:將 go mod tidy 整合到開發流程中,保持 go.mod 文件精簡。
  • 重大變更後:在添加或移除重要代碼後使用,確保依賴保持同步。
  • 排除故障:有時可協助解決模組相關的衝突或不一致問題。
  • go mod verify

go mod verify 確保專案 go.mod 文件中列出的依賴是有效的、可下載的,並且內容與 go.sum 中的校驗和相符。

主要特點

  • 依賴驗證:檢查所需的依賴是否存在於指定版本,並確認其內容與 go.sum 中的校驗和一致。
  • 完整性保證:減少外部依賴意外變更的風險,確保專案的可重現性。
# 在專案目錄中執行
go mod verify

# 輸出:
# 如果成功: "all modules verified"
# 如果發現問題:顯示指示具體依賴問題的錯誤訊息。

使用時機

  • 修改依賴後:每當更改 go.mod 文件中的版本或添加/移除依賴時使用。
  • 部署前:作為預部署檢查,確保專案將使用正確的依賴進行構建。
  • 定期驗證:考慮將其整合到開發流程或 CI/CD 管道中,進行持續的依賴健康檢查。
  • go mod vendor

go mod vendor 在專案目錄中創建一個 vendor 文件夾,包含所有專案所需依賴的本地副本。

主要特點

  • 自包含性:使專案獨立於外部模組倉庫。
  • 可重現性:確保構建一致,因為專案依賴於本地 vendored(下載的)依賴,而不受外部變更影響。
  • 離線開發:允許在無需網路訪問的情況下進行開發。
# 在專案目錄中執行
go mod vendor

使用時機

  • 隔離構建:確保專案總是使用相同的依賴,無論外部倉庫有何變更。
  • 離線環境:在網路連接有限或無法連接的環境中開發或部署專案。
  • 合規性需求:某些開發環境可能限制使用外部模組來源。

其他 Go 工具

  • go run

go run 提供了一種簡化的方式,在一步操作中編譯並執行 Go 代碼。非常適合快速測試代碼片段、實驗想法或運行小型 Go 腳本。

主要特點

  • 隱藏編譯過程:go run 在內存中臨時編譯代碼,無需創建獨立的可執行檔。
  • 快速原型:允許快速迭代代碼變更,無需等待完整的 go build 過程。
  • 臨時性:不保存輸出二進位檔,適合用於快速任務。
# 運行單一 Go 檔案
go run main.go

# 運行套件中的代碼
go run ./mypackage

使用時機

  • 實驗:嘗試 Go 代碼片段或探索套件功能。
  • 簡單腳本:執行小型、獨立的 Go 腳本。
  • 開發與除錯:在開發階段進行快速測試時使用。
  • go test

go test 是 Go 中自動化測試的基石,提供內建框架來編寫和執行單元測試,幫助確保代碼的正確性和穩健性。

主要特點

  • 測試發現:自動定位 Go 套件中的測試函數(以 Test 開頭,例如 TestAdd)。
  • 執行與報告:運行測試,提供成功、失敗及其他相關資訊的清晰輸出。
  • 測試覆蓋率:可生成代碼覆蓋率報告(go test -cover),識別未充分測試的代碼區域。
# 運行當前目錄中的所有測試
go test

# 運行特定套件的測試
go test ./mypackage

# 運行帶有詳細輸出的測試
go test -v

使用時機

  • 整個開發過程中:與代碼一起編寫測試,定期執行 go test 提升代碼質量,降低回歸風險。
  • 持續整合:將 go test 整合到 CI/CD 管道中,維持高標準的代碼可靠性。
  • go vet

go vet 是 Go 工具鏈中內建的靜態分析工具,能細緻掃描 Go 代碼,尋找潛在問題、低效率及樣式不一致。

主要特點

  • 問題檢測:識別常見問題,如可疑的代碼結構、格式錯誤及潛在的運行時錯誤。
  • 早期修正:在開發周期早期解決問題,防止其演變為更棘手的錯誤。
  • 自訂化:支持各種檢查,甚至可撰寫自訂分析器。
# 對當前套件執行推薦的 'vet' 檢查
go vet ./...

使用時機

  • 開發流程中:將 go vet 整合到開發過程中,主動捕捉錯誤。
  • 代碼審查前:在分享代碼前執行 go vet,進行預先的質量檢查。
  • 持續整合:將其納入 CI/CD 管道,強制執行代碼質量標準。
  • go link

go link 是 Go 編譯器內部使用的低級工具,提供對連結過程的精細控制,靈活性超越了標準的 Go 構建工作流程。

主要特點

  • 手動連結:允許直接連結物件檔和檔案庫,繞過通常的 Go 編譯器自動化。
  • 專業構建:可用於創建優化的可執行檔、靜態連結庫或微調最終輸出。
  • 內部操作:主要針對開發 Go 工具鏈本身或有特定構建需求的開發者。
# 將物件檔 'main.o' 和 'utils.o' 連結成可執行檔 'myprogram'
go link -o myprogram main.o utils.o

使用時機

  • 極少數情況:大多數 Go 開發者不需要直接控制 go link 提供的功能,標準 Go 工具通常能有效處理構建和連結過程。
  • 工具鏈開發:更可能被那些開發 Go 編譯器或構建系統的人員使用。
  • 高級優化:有潛在(但風險較高)的用例,如手動調整性能優化或高度自訂的構建。
  • go doc

go doc 提供了一種方便的方式,直接從終端機存取並閱讀 Go 套件的文件。它會提取並格式化代碼中的註釋,保持文件始終最新。

主要特點

  • 隨時獲取文件:無需頻繁切換代碼編輯器和外部網站查看套件參考資料。
  • 清晰簡潔:呈現套件、類型、函數、常數等的格式良好且易讀的文件。
  • 代碼範例:通常包含嵌入於代碼註釋中的使用範例。
# 顯示 'fmt' 套件的文件
go doc fmt

# 查看 'fmt' 套件中 `Println` 函數的文件
go doc fmt.Println

# 查詢專案中自訂類型的文件
go doc mypackage.MyCustomType

使用時機

  • 學習新套件:快速理解你尚未使用過的套件的目的和用法。
  • 回憶:詳細查詢特定函數或類型,即使是你自己的代碼中。
  • 離線訪問:在無法連接網路時,理想地參考 Go 文件。
  • 提示:go doc 也可將輸出作為 HTML,提供可瀏覽的體驗。欲獲得更強大的導航和搜尋功能,考慮使用專用的文件工具,如 godoc.org(或本地運行的 godoc 服務器)。
  • go version

go version 提供了一種快速查詢系統上安裝的 Go 版本的方法。這對於檢查相容性和故障排除至關重要。

主要特點

  • 版本細節:顯示具體的 Go 發行版本(例如 go1.19.5),以及操作系統和架構的詳細資訊。
  • 相容性管理:確保代碼在生產環境中運行的 Go 版本與開發和測試時使用的版本一致。
  • 故障排除輔助:在尋求幫助或報告錯誤時提供有用的版本資訊。
# 檢查 Go 版本
go version

使用時機

  • 專案設置:驗證是否擁有特定專案所需的 Go 版本。
  • 共享環境:在向合作者描述設置或尋求支援時,包含 go version 的輸出。
  • 更新後:確認成功安裝或升級 Go。

參考資料


上一篇
【Day21】Go 中的錯誤處理 | Error Handling 實踐指南
下一篇
【Day23】動態型結構 | 透過 reflect 提升 Golang 靈活性
系列文
Go 快 Go 高效: 從基礎語法到現代Web應用開發30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言