Go里优雅的使用全局配置

全局配置是一个单例,最简单的实现是使用一个全局变量,为了到处都可以使用到,所以常见的做法是有一个包,例如名字叫 global 或者诸如此类的,然后要用到的地方去导入,例如:

package handlers

import (
    "log"

    "github.com/jiajunhuang/demo/global"
)

func Ping() {
    log.Printf("%s", global.Config.RedisURL)
}

不过这样写起来挺麻烦的,所以,不如这样写。首先咱们照样有一个包,叫做 singleton,里面就有 Config 的单例方法:

package singleton

import (
	"sync"

	"github.com/kelseyhightower/envconfig"
)

var (
	config      *Config
	configMutex sync.Mutex
)

type Config struct {
	Debug bool   `envconfig:"debug"`
	DBURL string `envconfig:"db_url"`
}

func GetConfig() *Config {
	if config != nil {
		return config
	}

	configMutex.Lock()
	defer configMutex.Unlock()

	// double check
	if config != nil {
		return config
	}

	config = &Config{}
	envconfig.Process("APP_NAME", config)

	return config
}

于是,咱们就可以这样使用了:

package main

import (
    "github.com/jiajunhuang/demo/singleton"
)

func main() {
    // init config
	_ = singleton.GetConfig()

}

在别的包里,可以这样:

package handlers

import (
    "github.com/jiajunhuang/demo/singleton"
)

var (
	config = singleton.GetConfig()
)

func Haha() {
    println(config.DBURL)
}

若要问我区别,其实没啥太大的区别,只不过呢,写起来更简单了,只要写 config.Blabla 而不是 global.Config.Blabla

就是这样!


更多文章
  • 解决k8s cron无法读取环境变量的问题
  • 应用内购的坑
  • 两种常见的访问控制模型
  • gunicorn max-requests 选项的作用
  • Redis使用中的几点注意事项
  • 给你的代码跑个分?pylint使用教程
  • 一个Gunicorn worker数量引发的血案
  • MySQL Boolean类型的坑
  • pip freeze是魔鬼
  • 一个feed流系统的演进
  • Android 使用view binding
  • 系统调用的过程
  • MySQL charset不同导致无法使用索引的坑
  • 微服务的缺点
  • 远程工作一周有感