iT邦幫忙

3

小菜雞學程式!來說說 Golang 的環境變數吧!

之前有跟大家提過環境變數,其實可以想像成像是冷氣機的各種設定,像是溫度、功能、風向、風量等等,讓冷氣機運行的時候可以根據這些設定達到我們想要的樣子,那麼 Golang 也有些可供我們設定的環境變數,今天就來介紹一些比較常用到的幾個吧!

以下分別會介紹 GOROOTGOENVGOPATH 以及 GOOSGOARCH


首先,如果你想知道 Golang 的環境變數有哪些,你可以在你的終端機或是 iTerm2 裡輸入指令 go help environment,畫面上會列出 Golang 的環境變數,以及每一個變數的用途說明。

大家可以試著自己在終端機下指令後來查看哦!


如果你想知道你目前 Golang 的環境變數的值,你可以使用指令 go env 來列出環境變數目前設定的值是什麼,畫面如下:

如果只是想查看其中某幾個環境變數,那麼可以使用指令 go env KEY1 KEY2 ...,例如:go env GOPATH GOENV,輸出如下:

想要設定某一個環境變數,那麼你可以使用指令 go env -w KEY=VALUE,例如我如果想把 GOPATH 設定到家目錄底下的 go 資料夾,那麼指令就會是 go env -w GOPATH=$HOME/go

但要注意,其中的 GOENV 是不能用 go env -w GOENV=VALUE 來設定的,必須要用指令 export GOENV=VALUE 的方式來設定喔!

接下來就來分別針對其中幾個來做說明吧。


首先來講講 GOROOT, 這個環境變數在我們一開始下載安裝好 Golang 之後,就會有個初始設定了,這其實是當初安裝 Golang 的路徑喔,在這個路徑底下有內建的標準函式庫、還有執行檔如 gogofmt 等等,所以如果沒有其他特殊狀況,基本上是不需要自己另外再去設定這個環境變數的哦。

像我的話,一開始預設就是將 Golang 安裝在路徑 /usr/local/go 底下,因此剛剛的圖裡,顯示出來的 GOROOT 的值就自動設定為 /usr/local/go 囉。


第二個是 GOENV,這個變數他所要儲存的是一個檔案的路徑,也就是如果你想要在一個檔案裏面去設定各種 Golang 的環境變數的話,那麼就要把那個檔案存放的位置設定給 GOENV,要注意的是,那些你在檔案中有設定的環境變數,他是會壓過預設的值,還有使用指令 go env -w KEY=VALUE 來設定過的那些環境變數,如果在檔案中有設定的話也是會以檔案中的為主喔。

舉個例子,我在家目錄底下建立了一個檔案 test.env,裡面的內容設定了 GOOS 以及 GOARCH,內容如下:

GOOS=windows
GOARCH=amd64

而原本的 GOOSGOARCH 的值分別為:

現在我們使用指令 export GOENV=$HOME/test.env 來將我們剛剛寫好的 test.env 設定給 GOENV,接著再來看看設定完之後 GOOSGOARCH 的值是什麼吧,結果如下:

可以看到這兩個環境變數的值,都以我們檔案裡設定的為主囉!


再來要來介紹 GOPATH,這個環境變數在我們開發時可是非常重要的哦!他有點像是告訴 Golang 你的工作區域(Workspace)的感覺,一開始安裝好 Golang 之後,這個環境變數預設的值會是家目錄底下的 go/ ,也就是 $HOME/go,以我自己為例,就是 /Users/chrishuang/go

一開始雖然安裝好後會把 GOPATH 設為這個路徑,但如果這個路徑並不存在,是不會自動幫忙建立的,因此大家也可以思考看看,想要把哪裡當作你 Golang 的工作區域,然後用 go env -w GOPATH=VALUE 來設定喔,如果想直接以預設的路徑當作工作目錄,那也要記得在家目錄底下創建資料夾 go 喔。

一般來說,在這個路徑底下,我們還需要手動建立三個資料夾,分別是 binpkgsrc,他們是有不同用處的。

  1. bin:bin 是 binary 的意思,存放可執行檔的地方,像是我們使用指令 go install,而且在當前的路徑底下有 package main 的話(有func main()、也就是具有程式進入點),則會編譯出一個可以執行的檔案,這個檔案就會放在 GOPATH 底下的 bin/ 之中喔。

  2. pkg:pkg 則是 package,如果我們使用 Go Module 來管理專案中使用的套件,他就會將下載下來的套件依照 網域/作者/專案名 來擺放下載的套件,例如:github.com/joho/godotenv 將會擺放在路徑 $GOPATH/pkg/github.com/joho/godotenv 底下。

    另外當我們使用指令 go install 時,如果當前路徑底下沒有 package main,則不會產生可執行檔在 bin/ 底下,反而是會有副檔名 .a 的檔案產生在 pkg 裡面,而這樣產出的套件跟我們從 github 上下載下來的套件是一樣用法的來做使用哦,而詳細如何自己寫套件來做使用,以後會努力寫出更詳細的文章跟大家分享。

  3. src:src 其實就是 source code 的意思,主要是用來存放我們所開發的程式碼,可以再依照不同專案等等的分類方式,在這個資料夾內去擺放自己的程式碼檔案。

關於 GOPATH 的架構、如何編譯套件、如何將自己的程式編譯成可執行檔等等的說明,可以參考官方的說明文章,有更為詳細的說明及範例哦!
-> 請點這裡


最後 GOOS 以及 GOARCH 放在同一個區塊一起說明他們的用處,這兩個環境變數的功能是用來告訴 Golang 要將你的程式編譯成什麼系統、什麼指令集架構看得懂的執行檔,Golang 提供我們可以透過設定這兩個環境變數,就可以讓編譯出來的執行檔在不同的平台上執行哦!

但是 GOOSGOARCH 的搭配並不是隨便我們填寫的,只有有被表列出來的組合才能使用,可以的組合可以參考底下的連結中,主題 Optional environment variables 底下的 $GOOS and $GOARCH 部分。
-> Optional environment variables

舉個例子,我先寫了一支簡單的 Hello World! 程式,內容如下:

package main

import "fmt"

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

接著先以 GOOS 設定為 darwinGOARCH 設定為 amd64 的組合來編譯出執行檔,這是我使用的 Mac 電腦作業系統及指令集架構,使用指令 go build 之後,產生出名為 helloworld 的執行檔,此時我們在終端機裡執行是毫無問題的。

如果我把產生的這個檔案,試著在 Windows 的作業系統底下去執行,他是完全沒辦法執行的。

此時如果我在使用指令編譯出執行檔之前,先將環境變數設定成 GOOSwindowsGOARCHamd64 的話,則這次編譯出來的執行檔 helloworld.exe 在我的 Mac 電腦上就無法執行了。

但相對的,這次產生的檔案在我作業系統是 Windows 的電腦裡,就可以很正常的執行哦。
但要提醒一下,因為程式跑完之後,開啟的視窗會立刻關掉,你可以用 Windows 內建的 CMD 或 PowerShell 來執行剛剛的 helloworld.exe,或是我們可以在剛剛的 Hello World! 程式裡面加上最後會等待使用者按下 Enter 才結束程式的程式碼,程式修改如下:

package main

import "fmt"

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

    fmt.Print("Press ENTER to leave!")
    fmt.Scanln()
}

修改後的程式碼,在 Windows 底下,就算直接滑鼠點擊兩次執行,還是可以看到輸出的結果囉,不會再一閃而過了,我們的輸出結果就會在傳說中的小黑窗裡出現啦!

所以我們就算是使用跟目標作業系統或指令集架構不一樣的環境下開發,也可以很輕鬆透過設定 GOOS 還有 GOARCH 來編譯出跨平台的執行檔喔。

但是要注意一點,當我們把這兩個環境變數設定成跟開發的環境不同,那麼我在開發環境下使用 go run main.go 指令要去執行程式時,也會出現不能執行的問題。

所以當我們只是要改變編譯出執行檔的目標作業系統集指令集時,可以不要直接修改 Golang 的環境變數,而是使用一個暫時性的設定,只讓當下的 go build 指令知道要更改成什麼值就好,因此我們指令修改成 GOOS=VALUE GOARCH=VALUE go build,例如:要編譯出作業系統為 Windows、指令集架構為 amd64 的執行檔,指令要用 GOOS=windows GOARCH=amd64 go build

如圖:我的 Golang 環境變數將 GOOS 設定成 Mac 電腦的 darwin 系統,但是透過上述的 GOOS=windows GOARCH=amd64 go build 指令,還是成功的編譯出了在 Windows 底下可以使用的 helloworld.exe 執行檔囉!


以上是今天分享的內容,如果內容有誤或是有什麼心得想與我討論,都歡迎在底下留言哦!
謝謝大家!


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言