在Go語言中,配置文件的讀取有多種方式,每種方式都有其優(yōu)缺點。以下是一些最佳實踐:
encoding/json
或encoding/yaml
對于JSON和YAML格式的配置文件,可以使用Go標(biāo)準(zhǔn)庫中的encoding/json
和encoding/yaml
包來讀取。
package main
import (
"fmt"
"io/ioutil"
"gopkg.in/yaml.v2"
)
type Config struct {
Database struct {
Host string `yaml:"host"`
Port int `yaml:"port"`
User string `yaml:"user"`
Password string `yaml:"password"`
} `yaml:"database"`
}
func main() {
data, err := ioutil.ReadFile("config.yaml")
if err != nil {
panic(err)
}
var config Config
err = yaml.Unmarshal(data, &config)
if err != nil {
panic(err)
}
fmt.Printf("Host: %s, Port: %d, User: %s, Password: %s\n",
config.Database.Host, config.Database.Port, config.Database.User, config.Database.Password)
}
viper
viper
是一個功能強大的配置解決方案,支持多種配置格式,并且可以輕松地將配置映射到結(jié)構(gòu)體。
package main
import (
"fmt"
"github.com/spf13/viper"
)
type Config struct {
Database struct {
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
User string `mapstructure:"user"`
Password string `mapstructure:"password"`
} `mapstructure:"database"`
}
func main() {
viper.SetConfigName("config") // 配置文件名(不帶擴展名)
viper.AddConfigPath(".") // 配置文件路徑
viper.SetConfigType("yaml") // 配置文件類型
if err := viper.ReadInConfig(); err != nil {
panic(err)
}
var config Config
if err := viper.Unmarshal(&config); err != nil {
panic(err)
}
fmt.Printf("Host: %s, Port: %d, User: %s, Password: %s\n",
config.Database.Host, config.Database.Port, config.Database.User, config.Database.Password)
}
對于敏感信息,如數(shù)據(jù)庫密碼,可以使用環(huán)境變量來存儲配置。
package main
import (
"fmt"
"os"
)
type Config struct {
Database struct {
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
User string `mapstructure:"user"`
Password string `mapstructure:"password"`
} `mapstructure:"database"`
}
func main() {
config := Config{}
config.Database.Host = os.Getenv("DB_HOST")
config.Database.Port = 5432
config.Database.User = os.Getenv("DB_USER")
config.Database.Password = os.Getenv("DB_PASSWORD")
fmt.Printf("Host: %s, Port: %d, User: %s, Password: %s\n",
config.Database.Host, config.Database.Port, config.Database.User, config.Database.Password)
}
可以使用flag
包來解析命令行參數(shù)。
package main
import (
"flag"
"fmt"
)
type Config struct {
Database struct {
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
User string `mapstructure:"user"`
Password string `mapstructure:"password"`
} `mapstructure:"database"`
}
func main() {
host := flag.String("host", "localhost", "Database host")
port := flag.Int("port", 5432, "Database port")
user := flag.String("user", "root", "Database user")
password := flag.String("password", "", "Database password")
flag.Parse()
config := Config{}
config.Database.Host = *host
config.Database.Port = *port
config.Database.User = *user
config.Database.Password = *password
fmt.Printf("Host: %s, Port: %d, User: %s, Password: %s\n",
config.Database.Host, config.Database.Port, config.Database.User, config.Database.Password)
}
可以使用viper
庫的MergeInConfig
方法來合并多個配置文件。
package main
import (
"fmt"
"github.com/spf13/viper"
)
type Config struct {
Database struct {
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
User string `mapstructure:"user"`
Password string `mapstructure:"password"`
} `mapstructure:"database"`
}
func main() {
viper.SetConfigName("config") // 配置文件名(不帶擴展名)
viper.AddConfigPath(".") // 配置文件路徑
viper.SetConfigType("yaml") // 配置文件類型
if err := viper.ReadInConfig(); err != nil {
panic(err)
}
var config Config
if err := viper.Unmarshal(&config); err != nil {
panic(err)
}
fmt.Printf("Host: %s, Port: %d, User: %s, Password: %s\n",
config.Database.Host, config.Database.Port, config.Database.User, config.Database.Password)
}
encoding/json
或encoding/yaml
。viper
庫,它支持多種格式和靈活的配置方式。flag
包來解析命令行參數(shù)。viper
庫的MergeInConfig
方法來合并多個配置文件。選擇哪種方式取決于你的具體需求和應(yīng)用場景。