项目中经常会有这样的需求,一个项目部署在不同的服务器上,而不同的服务器上的配置是不同的,例如一个项目,即部署在国内,又部署在美东,但是国内是国内的一套数据库、redis等等,而国外又是连接国外的数据库、redis等等,这样就需要我们根据部署的环境去加载响应的配置。
那么在go程序启动main运行的时候,我们往往就要加载响应的配置。
一般部署都是在项目中的.sh脚本文件里,我们在脚本文件里去得到当前的服务器是在国内还是国外,然后依此将服务器发信息传递到go里。
例如,项目中有一个start.sh文件,我们项目根目录有一个conf文件夹
结构如下:
conf/test1/log.conf
conf/test1/mysql.conf
conf/test1/redis.conf
conf/test2/log.conf
conf/test2/mysql.conf
conf/test2/redis.conf
在sh文件里我们判断了当前服务器为test2,在sh文件里
// 即为将config_conf变量的值传递给go代码
// 注意,这里的 -后面的d,即为flag.String里的第一个参数,第一个参数写的啥,这里的-后面就是啥
exec "./bin/$app" -d "$config_conf"
// 此时config_conf值为conf/test2
下面我们来看go代码
var (
defaultPath = flag.String("d", "./conf/test1/", "conf path")
LogFile = *defaultPath + "log.json"
confFile = *defaultPath + "redis.toml"
Cfg Config
)
// InitConf 初始化配置文件
func InitConf() error {
flag.Parse()
// 如果下面不重新赋值,那么logfile与confile的值仍旧为旧值,即
// ./conf/test1/...
LogFile = *defaultPath + "log.json"
confFile = *defaultPath + "project.toml"
fmt.Println(LogFile)//conf/test2/log.conf
fmt.Println(confFile)//conf/test2/redis.conf
至此,go代码中就读取到配置文件的信息了。
再来看下flag.Parse()的源码及注释,啥意思呢,就是在变量定义之后,程序访问标志之前去调用该函数,注意flag.String("d"第一个参数,写的是谁,那么.sh文件里的 exec "./bin/ a p p " − d " app" -d " app"−d"config_conf"的-d就是谁,例如flag.String第一个参数为-c那么exec "./bin/ a p p " − c " app" -c" app"−c"config_conf"里就是-c
// Parse parses the command-line flags from os.Args[1:]. Must be called
// after all flags are defined and before flags are accessed by the program.
func Parse() {
// Ignore errors; CommandLine is set for ExitOnError.
CommandLine.Parse(os.Args[1:])
}
上面的注释啥意思呢,就是在变量定义之后,程序访问标志之前去调用该函数。
即下面代码中LogFile、confFile都已在var定义过了,然后还并没有使用defaultPath标志变量,然后flag.Parse()函数会将运行命令中的参数通过d这个标志赋值给defaultPath,然后flag.Parse()之后的代码再去取defaultPath的值的时候就拿到了运行命令传递过来的值,即/conf/test2/
var (
defaultPath = flag.String("d", "./conf/test1/", "conf path")
LogFile = "log.json"
confFile = "redis.toml"
Cfg Config
)
// InitConf 初始化配置文件
func InitConf() error {
flag.Parse()
// 如果下面不重新赋值,那么logfile与confile的值仍旧为旧值,即
// ./conf/test1/...
LogFile = *defaultPath + "log.json"
confFile = *defaultPath + "project.toml"
fmt.Println(LogFile)//conf/test2/log.conf
fmt.Println(confFile)//conf/test2/redis.conf
如果下面这样写是不对的,下面的代码在 flag.Parse()之后并没有去将defaultPath的新值赋值给LogFile、confFile所以运行时取到的还是defaultPath定义的旧值,即./conf/test1/
var (
defaultPath = flag.String("d", "./conf/test1/", "conf path")
LogFile = *defaultPath + "log.json"
confFile = *defaultPath + "redis.toml"
Cfg Config
)
// InitConf 初始化配置文件
func InitConf() error {
flag.Parse()
其实无论是c语言还是golang语言或是其他语言,启动应用程序时都可以带一些参数,然后系统根据传入的参数进行特点的工作。如:./main -b /home/backupdir -d true
package main
import (
"flag"
"fmt"
)
func main() {
backup_dir := flag.String("b", "/home/default_dir", "backup path")
debug_mode := flag.Bool("d", false, "debug mode")
flag.Parse()
fmt.Println("backup_dir: ", *backup_dir)
fmt.Println("debug_mode: ", *debug_mode)
}
/**
启动命令:go run main.go -b /home/backup
输出结果:
backup_dir: /home/backup // 因为指定了路径,所以覆盖了默认路径
debug_mode: false // 启动命令里不带 -d 参数,所以启用默认值
*/