读取.env到结构体

用gin写一个练手项目时,始终没找到中意的配置管理包,读取.env环境文件也没找到比较好用的,决定自己写个简单的玩玩!

发现的包如下:

https://github.com/caarlos0/env/v6

https://github.com/joho/godotenv

https://github.com/go-ini/ini

目录结构,项目根目录创建config文件夹,用于存放所有相关的配置文件

结构

image.png

配置内容如下

image.png

大概思路,先把.env拆分成map, 再读取相关结构体tag配置对应的值, app.go文件内容如下

package config

import (
    "bufio"
    "fmt"
    "io"
    "os"
    "reflect"
    "regexp"
    "strconv"
    "strings"
)

type AppConfig struct {
    // 版本号
    Version string `env:"VERSION"`
    // 运行模式
    RunMode string `env:"RUN_MODE"`
    // 服务端口
    HTTPPort int `env:"HTTP_PORT"`
    // 读写超时
    ReadTimeout  int64 `env:"READ_TIMEOUT"`
    WriteTimeout int64 `env:"WRITE_TIMEOUT"`
    // 分页每一页数量
    PageSize int `env:"PAGE_SIZE" default:"10"`
}

var (
    App   AppConfig
    Mysql MysqlConfig
    Redis RedisConfig
    Jwt   JwtConfig
    Qiniu QiniuConfig
)

var config = make(map[string]string)

func init() {
    inputFile, inputError := os.Open("./.env")
    if inputError != nil {
        fmt.Printf("open env file error: %s!", inputError.Error())
        return
    }
    defer inputFile.Close()

    inputReader := bufio.NewReader(inputFile)
    var reg *regexp.Regexp
    for {
        inputString, readerError := inputReader.ReadString('\n')
        if readerError == io.EOF {
            break
        }

        reg = regexp.MustCompile("\\s+")
        if reg.ReplaceAllString(inputString, "") == "" {
            continue
        }
        s := strings.Split(inputString, "=")
        s[1] = strings.Trim(s[1], "\r\n")
        s[1] = strings.Trim(s[1], "\"")
        config[s[0]] = s[1]
    }
    reflectParse(&App)
    reflectParse(&Mysql)
    reflectParse(&Redis)
    reflectParse(&Jwt)
    reflectParse(&Qiniu)
}

func reflectParse(c interface{}) {
    rValue := reflect.ValueOf(c)
    rType := reflect.TypeOf(c)
    if rType.Kind() != reflect.Ptr {
        fmt.Print("Can only be pointer type")
        return
    }
    rValue = rValue.Elem()
    rType = rType.Elem()
    for i := 0; i < rType.NumField(); i++ {
                 envValue := ""
        tField := rType.Field(i)
        vField := rValue.Field(i)

        env := tField.Tag.Get("env")
        dValue := tField.Tag.Get("default")

        if env != "" {
            configValue, ok := config[env]
            if ok {
                envValue = configValue
            }
        } else if dValue != "" {
            envValue = dValue
        }

        rFieldType := tField.Type.Kind()
        if rFieldType == reflect.String {
            vField.Set(reflect.ValueOf(envValue))
        } else if rFieldType == reflect.Int {
            envValue, _ := strconv.Atoi(envValue)
            vField.Set(reflect.ValueOf(envValue))
        } else if rFieldType == reflect.Int64 {
            envValue, _ := strconv.ParseInt(envValue, 10, 64)
            vField.Set(reflect.ValueOf(envValue))

        }
    }
}

使用

例如: gin main.go

package main

import (
    "fmt"
    "github.com/putyy/ai-share-server/config"
    "github.com/putyy/ai-share-server/router"
    "net/http"
    "time"
)

func main() {
    s := &http.Server{
        Addr:           fmt.Sprintf(":%d", config.App.HTTPPort),
        Handler:        router.InitRouter(),
        ReadTimeout:    time.Duration(config.App.ReadTimeout) * time.Second,
        WriteTimeout:   time.Duration(config.App.WriteTimeout) * time.Second,
        MaxHeaderBytes: 1 << 20,
    }
    s.ListenAndServe()
}

原文地址
原文地址
原文地址

go
本作品采用《CC 协议》,转载必须注明作者和本文链接
LW放下
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!