1. 程式人生 > 其它 >go語言中包的使用

go語言中包的使用

在golang中,所有原始檔都屬於一個包,golang的包具有以下特性:包可以被其他包引用;每個golang程式只有一個main包;包的主要用途是提高程式碼的可複用性

在golang中,所有原始檔都屬於一個包,golang的包具有以下特性:

  • 包可以被其他包引用
  • 每個golang程式只有一個main包
  • 包的主要用途是提高程式碼的可複用性

本節,我們將介紹包的相關概念以及使用方法,如果你還沒有閱讀過前面的文章,可以通過以下連結進行閱讀

一. GOPATH 環境變數

1. 什麼是GOPATH?

golang包的使用依賴一個重要的環境變數:GOPATH,無論是自己的程式碼還是第三方程式碼,都以GOPATH作為工作目錄和一套完整的工程目錄規則。GOPATH目錄約定有三個子目錄,主要用於

  • src:存放各種包原始碼,src裡的一個目錄就是一個包
  • pkg:存放編譯原始碼後的類庫
  • bin:存放編譯原始碼後的可執行程式

GOPATH允許多個目錄,設定多個目錄時,需要使用環境變數分隔符來區分。Unix/Linux的環境變數分隔符是英文輸入法下的冒號(:),windows的環境變數分隔符是英文分號(;)。

使用GOPATH時,golang會在以下目錄中搜索包:

    1. GOROOT/src:該目錄儲存了Go標準庫裡程式碼。
    1. GOPATH/src:該目錄儲存了應用自身的程式碼和第三方依賴的程式碼。

2. 設定GOPATH環境變數

在Unix/Linux中,使用sudo vim /etc/profile開啟系統profile檔案,並追加以下內容設定GOPATH

環境變數,同時設定GO111MODULE為關閉狀態,GO111MODULE環境變數我們在文章中後面部分說明

export GOPATH=/Users/pan/go # 把自己的golang專案目錄作為GOPATH的變數
export GO111MODULE=off # 關閉golang 11.1 版本以後的模組功能

使用source /etc/profile命令重新載入環境變數

3. 包的使用

(1)main包與包的引入

a. 引入系統包

我們可以通過package關鍵字定義一個包,使用import引入其他包,如果需要引入多個包,可以將各個包宣告在括號內

package main

import (
	// 引入系統的包
	"fmt"
)

func main() {
	// 呼叫系統包的函式
	fmt.Println("Hello World")
}

在以上程式碼中,我們通過main關鍵字定義了main包,主函式main必須位於main包下。程式中引入了fmt包,該包由golang本身提供。

b. 引入自定義包
我們在GOPATH/src目錄下建立兩個檔案:
檔案1,庫檔案位於jkdev.cn/test/mypkg/lib.go,新增以下程式碼

package mypkg

import "fmt"

func TestFunc() {
	fmt.Println("call testFunc")
}

檔案2,主檔案jkdev.cn/test/main.go,新增以下程式碼

package main

// 引入自定義包
import "jkdev.cn/test/mypkg"

func main() {
	// 呼叫自定義包的函式
	mypkg.TestFunc()
}

自定義的包由我們自己定義,但要注意的是,一個目錄對應一個包,同時,包名應當和目錄名一致。引入包時,路徑相對應GOPATH/src,我們可以根據自己的程式的功能模組劃分不同的包。

(2)包的作用域

  • 包內:在同一個包內定義的函式、變數、常量、結構體,可以被包內的所有其他程式碼任意訪問,它們屬於包內公開。

  • 包外:如果函式、變數、常量、結構體位於不同的包下,如果將它們的首字母使用大寫標識,表示它們是公開訪問的。對於結構體欄位。如果想要在包外進行訪問,還要讓結構體欄位變數名使用首字母大寫。

二. 編譯

golang中go build 命令主要用於編譯程式碼。在包的編譯過程中,若有必要,會同時編譯與之相關聯的包。

假設我們的設定GOPATH是/Users/pan/go,我們在GOPATH之下的src建立建立程式碼test目錄,並新增lib.gomain.go兩個檔案:

此時,原始檔相對於GOPATH的路徑如下。接下來我們對這兩個go原始檔進行編譯

go  GOPATH目錄
├─src                  原始碼目錄
│  ├─test              專案目錄
│     ├─lib.go         公共函式檔案
│     └─main.go        主函式檔案

lib.go 程式碼如下:

package main

import "fmt"

func testFunc() {
	fmt.Println("call testFunc")
}

main.go程式碼如下:

package main

func main() {
	testFunc()
}

示例中的兩個原始檔都屬於main包,所以在main.go檔案中能正常引入lib.go檔案。

1. go build

無引數編譯不依賴GOPATH,需要在原始碼目錄下進行編譯

# 進入原始碼目錄
cd ~/go/src/test
# 編譯程式碼
go build

我們還可以-o指定編譯後輸出的可執行檔案的檔名,如下

go build -o main

2. go build 檔案列表

使用“go build+檔案列表”編譯時,檔案列表中的每個檔案必須是同一個包的 Go 原始碼

# 進入原始碼目錄
cd ~/go/src/test
# 編譯
go build lib.go main.go

3. go build 包

包的路徑相對於GOPATH,“go build+包”編譯時,原始檔需要存放在GOPATH/src下的路徑,但是我們可以在任意有讀寫許可權的目錄執行編譯命令,如下

# test 相對於GOPATH/src
go build test

4. go install

go build具有相似功能的是go install命令,go install用來生成庫和工具並存放於GOPATH中。一是編譯包檔案(無main包),將編譯後的包檔案放到 pkg 目錄下(GOPATH/pkg)。二是編譯生成可執行檔案(有main包),將可執行檔案放到 bin 目錄(GOPATH/bin)。

5. go build 和 go install 對比

  • 相同點:都能生成可執行檔案
  • 不同點:go build 不能生成包檔案, go install 可以生成包檔案;go build 生成可執行檔案在當前目錄下, go install 生成可執行檔案在bin目錄下($GOPATH/bin)。

三、 Go模組

golang在1.11版本引入和Go Modules,我們還可以叫做Go模組,模組依賴於上文提到的GO111MODULE環境變數。它是golang官方提供的包管理工具,通過Go Modules,我們可以不必將專案放在GOPATH上。

1. GO111MODULE環境變數

用環境變數GO111MODULE設定開啟或者關閉模組支援,它有三個可選值:off、on、auto,預設是auto。

  • GO111MODULE=off:無模組支援,go會從GOPATH尋找包。
  • GO111MODULE=on:模組支援,根據go.mod檔案下載依賴
  • GO111MODULE=auto:在$GOPATH/src外面且專案根目錄有go.mod檔案時,自動開啟模組支援

在使用模組的時候,GOPATH是無意義的,但golang還是會把下載的依賴儲存於GOPATH之下。

2. 使用go模組

使用Go Modules時,我們先將GO111MODULE設定為on或者auto,Go Modules和GOPATH不同,不需要包含固定的三個字目錄。一個空的原始碼目錄,只要初始化好go.mod檔案,就可以定義一個Module。我們可以使用以下命令建立一個新的Module

# 建立一個空的工作目錄
mkdir -p ~/Work/go/test
# 進入工作目錄
cd ~/Work/go/test
# 初始化一個module
go mod init testmodule

我們可以看到自動生成的go.mod檔案的內容如下

module testmodule

go 1.16

(1)下載依賴

Go Modules會為我們進行包管理,並自動更新go.mod檔案,如果需要引入新的依賴,我們只需要在終端執行go get 包名即可引入第三方包,如

go get github.com/satori/go.uuid

執行命令後,Go Modules會從我們在安裝golang時設定的GOPROXY映象倉庫地址去下載對應的包,安裝完成之後我們看到go.mod已經發生變化,如下

module testmodule

go 1.16

require github.com/satori/go.uuid v1.2.0 // indirect

我們也可以先編輯好go.mod檔案,然後在終端使用go mod download,golang會自動幫我們下載依賴包到本地。如果我們需要引入多個包,將所有包名解除安裝括號內,如下程式碼

module testmodule

go 1.16

require (
	github.com/satori/go.uuid v1.2.0 // indirect
	gorm.io/gorm v1.21.11 // indirect
)

(2)更新依賴關係

使用go mod tidy更新依賴關係,該命令拉取缺少的模組,移除不用的模組。Go Modules可以輕易地進行一個包的依賴管理和版本控制,go buildgo install將自動使用go.mod中的依賴關係,減少了GOPATH管理時的複雜性。

本文介紹了Go的包的基本管理方法,後面,我們會循序漸進地介紹golang的基礎知識。如果喜歡,歡迎訂閱!