「Go開源包」Env:一個(gè)將系統(tǒng)環(huán)境變量解析到結(jié)構(gòu)體的庫
大家好,我是漁夫子。
今天給大家推薦一個(gè)將系統(tǒng)的環(huán)境變量獲取并解析到結(jié)構(gòu)體的包:env。
項(xiàng)目地址:https://github.com/caarlos0/envstar:3.7k 貢獻(xiàn)者:54 使用者:1.8k
該包的實(shí)現(xiàn)是基于標(biāo)準(zhǔn)庫os/env包中的相關(guān)函數(shù)(比如Getenv?)來獲取系統(tǒng)的環(huán)境變量的。獲取到環(huán)境變量值后,再通過結(jié)構(gòu)體中的tag,將值映射到對(duì)應(yīng)的結(jié)構(gòu)體字段上。
使用示例
下面是將系統(tǒng)的一些環(huán)境變量映射到config結(jié)構(gòu)體的示例。如下:
package main
import (
"fmt"
"time"
"github.com/caarlos0/env/v9"
)
type config struct {
Home string `env:"HOME"`
Port int `env:"PORT" envDefault:"3000"`
Password string `env:"PASSWORD,unset"`
IsProduction bool `env:"PRODUCTION"`
Hosts []string `env:"HOSTS" envSeparator:":"`
Duration time.Duration `env:"DURATION"`
TempFolder string `env:"TEMP_FOLDER,expand" envDefault:"${HOME}/tmp"`
}
func main() {
cfg := config{}
if err := env.Parse(&cfg); err != nil {
fmt.Printf("%+v\n", err)
}
fmt.Printf("%+v\n", cfg)
}
我們可以像以下這樣運(yùn)行該代碼:
$ PRODUCTION=true HOSTS="host1:host2:host3" DURATION=1s go run main.go
{Home:/your/home Port:3000 IsProduction:true Hosts:[host1 host2 host3] Duration:1s}
從上述示例中我們看到config結(jié)構(gòu)體中的字段有不同的類型。也就是說可以將環(huán)境變量解析成不同的數(shù)據(jù)類型。
接下來,我們看看env包都支持哪些數(shù)據(jù)類型。
支持的數(shù)據(jù)類型
env包支持的數(shù)據(jù)類型如下:
- string
- bool
- int
- int8
- int16
- int32
- int64
- uint
- uint8
- uint16
- uint32
- uint64
- float32
- float64
- time.Duration
- encoding.TextUnmarshaler
- url.URL
當(dāng)然,指針、切片、指針切片以及map這些數(shù)據(jù)類型也支持。同時(shí),該包還支持通過自定義類型解析函數(shù)來支持自定義的數(shù)據(jù)類型。
自定義類型解析函數(shù)
如果你要解析的數(shù)據(jù)類型不是go內(nèi)置的數(shù)據(jù)類型,那么你也可以通過自定義類型解析函數(shù)來進(jìn)行解析。下面示例演示了如何將環(huán)境變量的值映射到自定一的MyTime類型字段上。如下:
type MyTime time.Time
func (t *MyTime) UnmarshalText(text []byte) error {
tt, err := time.Parse("2006-01-02", string(text))
*t = MyTime(tt)
return err
}
type Config struct {
SomeTime MyTime `env:"SOME_TIME"`
}
我們定義了一個(gè)MyTime類型,同時(shí)給這個(gè)類型定義了一個(gè)UnmarshalText方法。這樣,在Config結(jié)構(gòu)體中就可以將SOME_TIME的環(huán)境變量值解析到Config的SomeTime字段上。
從文件中解析環(huán)境變量
env包通過給結(jié)構(gòu)體字段設(shè)置file標(biāo)簽就可以支持從文件中解析環(huán)境變量到結(jié)構(gòu)體上。如下:
package main
import (
"fmt"
"time"
"github.com/caarlos0/env/v9"
)
type config struct {
Secret string `env:"SECRET,file"`
Password string `env:"PASSWORD,file" envDefault:"/tmp/password"`
Certificate string `env:"CERTIFICATE,file,expand" envDefault:"${CERTIFICATE_FILE}"`
}
func main() {
cfg := config{}
if err := env.Parse(&cfg); err != nil {
fmt.Printf("%+v\n", err)
}
fmt.Printf("%+v\n", cfg)
}
可以通過以下方式運(yùn)行:
$ echo qwerty > /tmp/secret
$ echo dvorak > /tmp/password
$ echo coleman > /tmp/certificate
$ SECRET=/tmp/secret \
CERTIFICATE_FILE=/tmp/certificate \
go run main.go
{Secret:qwerty Password:dvorak Certificate:coleman}
如果需要了解更多該包的用處,請(qǐng)參考github上的官方文檔:https://github.com/caarlos0/env