· 2 分鐘閱讀
幫專案設定環境變數 - VIPER
大概在好幾個月前,我寫了一篇關於如何在 golang 設定環境變數的文章,怎麼優雅地設定環境變數是一件相當重要的事情,因此我寫了一個簡單的函式來做這件事。
當初的考量很簡單,如果有提供對應的 config 檔,就把裡頭的 key/value 用 os.Setenv 設定。之後在整個 App 當中,就可以直接使用 os.Getenv 來取值。
不過一旦要正式部署,難免會發現幾個問題:
- 設定檔不一定是用 yaml,也可能是用其他格式
- 有時希望透過外部服務(consul, etcd 等等)來注入環境變數,但目前的寫法是用
os.Getenv - 可以從不同的路徑讀取設定檔
- 可以透過 command line 設定變數
- 更多意想不到的問題
在小型專案中,這樣其實解決了我的問題,但一旦需要更彈性的設定方式,光是這樣還不夠。
而以上這些問題其實在 golang 已經有一套成熟的解決方案,叫做 Viper。
VIPER
VIPER 是一個功能相當強大的環境變數設定套件。它支援了下列功能:
- 預設值
- 支援不同格式的設定檔(
json,toml,yaml) - 可以監聽設定檔的變化(這樣就不用重開 server 了!)
- 可以從遠端伺服器拿取變數(例如
consul或etcd) - 可以使用
flag來獲取變數 - 可以從
reader來獲取變數,這代表你可以用不同的來源來設定變數。
基本使用
首先先用 go get 或 mod 下載 VIPER。
go get github.com/spf13/viper
func main() {
viper.SetDefault("AWS_ACCESS_TOKEN", "AWS123456789") // 設定預設值
viper.SetConfigName("config") // 指定 config 的檔名
viper.AddConfigPath("./config")
viper.ReadInConfig()
viper.AutomaticEnv()
}
SetDefault(key, value):設定預設值SetConfigName(name): 設定 config 的檔名,例如我們的設定檔叫做config.yml就叫做config,為什麼不用指定 type 呢?viper 會自動幫我們處理。AddConfigPath:可以設定多個資料夾ReadInConfig:要記得呼叫,才會真的讀取設定AutomaticEnv:可以自動將ENV的變數同步到 viper 當中
viper 還有提供許多函數方便設定。
取用變數
設定完變數後,我們可以用 viper.Get 來讀取。Get 回傳的是一個 interface{},但 viper 也提供許多型別轉換,例如 viper.GetString、viper.GetDuration、viper.GetStringMap 等等。
func main() {
fmt.Println(viper.GetString("AWS_ACCESS_TOKEN"))
fmt.Println(viper.GetUint32("YOUR_INT"))
fmt.Println(viper.GetTime("YOUR_TIME"))
}
總結
變數設定說難不難,說簡單不簡單,要考慮的事情比想像中的還多,而 VIPER 幫我們處理掉了很多常見的使用情景。
另外要特別提醒的一點是,在設定像是 access token 或是 secret key 的時候,一定要記得用 .gitignore 掉,避免 commit 時意外推送到 github 上,造成遺憾。
相關文章
- 當測量變成目標:從窗戶稅到 Pull Request 數 我曾寫小工具統計自己一季貢獻了多少 PR、留了多少 review、解了多少 ticket,想拿數字向主管證明產出。主管只淡淡說績效不只看產出。幾年後我才懂——當測量變成目標,它就不再是一個好的測量了。從英國窗戶稅、河內滅鼠賞金,到今天用 PR 數評估開發者,機制一模一樣。
- 用 Cloudflare Images 當作圖片儲存、轉檔方案 在網頁放一張圖片是前端最簡單的事,但要把它做完整,包含縮放、生出各種格式、還要擋住流量,其實是一整個解決方案。我後來一律交給 Cloudflare Images,只留一份原圖給它。
- 別再用 AWS Access Key 了 Access Key 是 AWS 上容易被忽略的安全風險。用 OIDC 搭配 IAM Role,讓 GitHub Actions 不需要任何 secret 就能安全操作 AWS 資源
- 資料庫主鍵:AUTO_INCREMENT、UUID 與 UUIDv7 後端開發常需要決定主鍵,要用 auto increment 還是 UUID?碰撞怎麼辦?UUIDv7 跟 created_at + index 的效能差多少?實際跑了 2000 萬筆資料與設計決策告訴你