go env part 1
Published: 2022-03-13 08:21:06

วันนี้จะอธิบายค่า env ของภาษา go บางส่วนเท่าที่ใช้กันบ่อยๆว่ามันมีอะไรบ้างและใช้ทำอะไรนะครับ

วิธีดู env ของ go ทำได้ด้วยการรันคำสั่ง

```sh
go env
```

จะได้ผลลัพธ์ออกมาประมาณนี้ ซึ่ง version ที่ผมใช้ตอนนี้คือ `go1.18rc1 darwin/arm64`

```ini
GO111MODULE=""
GOARCH="arm64"
GOBIN=""
GOCACHE="/Users/pallat/Library/Caches/go-build"
GOENV="/Users/pallat/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/pallat/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/pallat/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/Users/pallat/sdk/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/Users/pallat/sdk/go/pkg/tool/darwin_arm64"
GOVCS=""
GOVERSION="go1.18rc1"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/dev/null"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/bz/hndgj2qd4n3_57k3y1l752tc0000gq/T/go-build1263010388=/tmp/go-build -gno-record-gcc-switches -fno-common"
```
เราจะไม่อธิบายทุกค่าตอนนี้นะครับ แต่จะอธิบายค่าที่อาจจะมีโอกาสใช้บ่อยๆก่อน

ก่อนอื่นขออธิบาย 4 ตัวนี้ก่อน เนื่องจากมีความเกี่ยวข้องกัน นั่นก็คือ

**GOOS, GOARCH, GOHOSTOS, GOHOSTARCH**

**GOHOSTOS** คือ OS ของ Go binary ที่กำลังใช้อยู่ในเครื่องนั้น เช่นถ้าเราใช้ MacOs ค่านี้จะเป็น `darwin` เป็นต้น

**GOOS** คือ OS ที่จะนำไป execute หรือพูดง่ายๆก็คือ ใช้กำหนด OS ที่ต้องการเอาโปรแกรมที่เราเขียนไปรันเมื่อ compile ออกมาแล้ว ยกตัวอย่างเช่น เราเขียนโค้ดอยู่บน Mac ซึ่ง GOOS จะเริ่มต้นที่ค่า `darwin` เพราะเรา compile เครื่องไหน เราก็สามารถ รันที่เครื่องนั้นได้โดยตรง แต่ถ้าต้องการ compile แล้วให้ไปรันที่ OS อื่นเช่น `linux` เราก็แค่เปลี่ยนค่า GOOS=linux ก็จะสามารถ compile โปรแกรมไปรันบน linux ได้เลย

**GOHOSTARCH** ก็คล้าย GOHOSTOS คือเป็น architecture ของ CPU ของ Go binary ที่เราใช้ในเครื่องนั้น เช่น ถ้าเราใช้บนเครื่อง Mac ที่มี CPU เป็น M1 ค่านี้ก็จะเป็น `arm64` เป็นต้น

**GOARCH** คือ architecture ที่จะทำเอาโปรแกรมไป execute หรือพูดง่ายๆคือ อยากให้ compile โปแกรมไปรันบน CPU แบบไหน ก็สามารถกำหนดได้ที่ค่านี้ เช่นเราเขียนบน CPU M1 แต่อยากเอาไปรันบน CPU intel ก็สามารถกำหนดค่านี้เป็น `GOARCH=amd64` เป็นต้น

ซึ่งค่า OS/ARCH สามารถดู list ได้ด้วยคำสั่งนี้

```sh
go tool dist list
```

ส่วนวิธีการกำหนดค่าเหล่านี้ สามารถกำหนดลงไปตรงๆที่ OS env ได้เลย เช่นถ้าใน linux/MacOS สามารถใช้คำสั่ง

```sh
export GOOS=linux
```

แบบนี้ได้เลย หรือสามารถสั่งให้ Go จำค่านี้ไว้เองก็ได้ด้วยการใช้คำสั่ง

```sh
go env -w GOOS=linux
```

เป็นต้น

และเมื่อพูดถึงเรื่องการใช้คำสั่งนี้ ก็เลยจะต้องกล่าวถึงอีกค่าหนึ่งนั่นก็คือ

**GOENV** ใช้กำหนด file ที่จะเก็บค่า env ที่เราสั่งผ่านคำสั่งเมื่อครู่นี้นั่นเองโดยเบื้องต้นมันจะมีค่า default ตั้งมาให้อยู่แล้วด้วย เพียงแต่ถ้ายังไม่เคยมีการ override ค่าใดใด มันก็อาจจะยังไม่มีไฟล์นั้นเกิดขึ้นมา

**GOROOT** ค่านี้จะเป็น root directory ของ go toolchain ที่เราติดตั้งไว้บนเครื่อง ซึ่งถ้าเราติดตั้งด้วยตัว installer มันจะเอา go toolchain ไปวางไว้ที่ใดที่หนึ่งเช่น `GOROOT="/usr/local/go"` แต่ถ้าเราติดตั้งเอง เมื่อ download go ลงมาและ extract เรียบร้อย จะได้ directory ชื่อ go มาตัวหนึ่ง เราสามารถเอา directory นี้ไปวางไว้ที่ไหนก็ได้ตามที่เราต้องการ และก็กำหนดค่า GOROOT ให้ชี้ไปตรงนั้น

**GOPATH** ค่านี้คือ workspace ที่ถูกกำหนดให้เราไปเขียนโปรเจ็คเราไว้ในนั้น แต่นั่นคือก่อนหน้าที่เราจะมี Go module คือก่อน Go version 1.11 ปัจจุบันใน GOPATH จะยังคงใช้เก็บค่า default path ของ module ต่างๆที่เราใช้เป็น dependencies ซึ่งค่าเหล่านั้นก็สามารถกำหนดเป็นที่อื่นๆได้เช่นกัน

> **ข้อควรระวัง** อย่ากำหนดค่า GOROOT และ GOPATH เป็นที่เดียวกัน

**GOBIN** เป็นค่า directory สำหรับวางไฟลื binary ที่เกิดจากคำสั่ง `go install` ซึ่งส่วนใหญ่จะเป็น tools ที่เขียนขึ้นจากภาษา Go เช่น `gosec` ที่เราใช้ scan AST เมื่อติดตั้งด้วยคำสั่ง `go install github.com/securego/gosec/v2/cmd/gosec@latest` ก็จะเกิด binary อยู่ใน $GOBIN นั่นเอง เพราะฉะนั้น $GOBIN ก็ควรถูก append ลงไปในค่า env PATH ของ OS ด้วย เพื่อให้เราสามารถเรียกใช้ binary นั้นได้โดยตรงจากที่ใดก็ได้

**GOMOD** ค่านี้จะชี้ไปที่ไฟล์ go.mod เสมอ ถ้าเราอยู่ใน project ที่ใช้ go module แต่ถ้าเราอยู่นอก project ค่านี้จะชี้ไปที่ os.DevNull เช่น `/dev/null` บน linux แต่ถ้าเราใช้คำสั่ง `go env` ใน directory ของ project ที่มีไฟล์ go.mod มันก็จะชี้ไปที่ไฟล์นั้นแทน

**GOMODCACHE** ค่านี้เป็น directory ที่ชี้ไปที่ module ที่เรา `go get` มาจากภายนอก จะถูกนำมารวมไว้ใน directory นี้ และเราสามารถเคลียร์มันได้ด้วยคำสั่ง `go clean -modcache`

**GOCACHE** ค่านี้เป็น directory ที่ใช้เก็บ cache ต่างๆที่คำสั่ง go จะเอามาใช้ในอนาคตได้ ยกตัวอย่างเช่น เมื่อเราใช้คำสั่ง `go run main.go` ความจริงมันจะเกิดการ compile และนำ binary ไปวางไว้ที่ $GOCACHE นี่แหล่ะ และสามารถเคลียร์ได้ด้วยคำสั่ง `go clean -cache`

วันนี้ก็ขออธิบายไว้เท่านี้ก่อนนะครับ แล้วจะมาต่อค่าอื่นๆในโอกาสต่อไป