wx

关注公众号领取Go学习资料

wx

洋葱小店

01:基础功能封装


Kratos入库文件 cmd//main.go 中的逻辑大致分为:

  • 接收命令参数
  • 创建日志对象 Logger
  • 读取配置文件

接下来我们将这部分通用代码进行封装;代码将放到项目目录的pkg/bootstrap 下

启动参数处理

为了是程序更加灵活通常会将一些参数在程序启动时传入;比如运行环境,配置文件路径等;接下来我们已接收conf(本地 文件配置); env (运行环境如 dev 开发 ;pro 生产);consul (consul 远程配置 地址) 三个参数为例进行封装;代码:

package bootstrap

import "flag"

type CommandFlags struct {
	Conf   string // 文件配置
	Env    string // 运行环境 dev 开发 ;pro 生产
	Consul string // consul 远程配置 地址
}

func NewCommandFlags() *CommandFlags {
	return &CommandFlags{
		Conf:   "",
		Env:    "",
		Consul: "",
	}
}

func (f *CommandFlags) Init() {
	flag.StringVar(&f.Conf, "conf", "../../configs", "config path, eg: -conf bootstrap.yaml")
	flag.StringVar(&f.Env, "env", "dev", "runtime environment, eg: -env dev")
	flag.StringVar(&f.Consul, "consul", "", "config server host, eg: -consul http://127.0.0.1:8500")
}

接收命令行参数用到了flag包;需要注意的是在入库文件调用封装方法后需要执行 flag.Parse() 如:

func init() {
	Flags   = bootstrap.NewCommandFlags()
	Flags.Init()
    flag.Parse()
}

日志处理

Kratos提供了统一的日志处理组件和日志接入抽象;通过实现Logger 对象可以很方便的实现自定义日志处理逻辑;log.DefaultLogger 可以将日志信息打印到控制台;如果将日志输出到文件中可以考虑通过zap包做封装;代码可以参考kratos-example代码如下:

import (
	"fmt"
	"os"
	"time"

	"github.com/go-kratos/kratos/v2/log"
	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

var _ log.Logger = (*ZapLogger)(nil)

// ZapLogger is a logger impl.
type ZapLogger struct {
	log  *zap.Logger
	Sync func() error
}

// NewZapLogger return a zap logger.
func NewZapLogger(encoder zapcore.EncoderConfig, prefix string, level zap.AtomicLevel, opts ...zap.Option) *ZapLogger {
	rotateLogger, err := rotatelogs.New("./log/"+prefix+"_%Y%m%d.log", rotatelogs.WithMaxAge(time.Hour*24*30))
	if err != nil {
		log.Fatalf("logger.Setup err: %v", err)
	}
	core := zapcore.NewCore(
		zapcore.NewConsoleEncoder(encoder),
		zapcore.NewMultiWriteSyncer(
			zapcore.AddSync(os.Stdout),    //输出到控制台上
			zapcore.AddSync(rotateLogger), //输出到文本中
		), level)
	zapLogger := zap.New(core, opts...)
	return &ZapLogger{log: zapLogger, Sync: zapLogger.Sync}
}

func (l *ZapLogger) Log(level log.Level, keyvals ...interface{}) error {
	if len(keyvals) == 0 || len(keyvals)%2 != 0 {
		l.log.Warn(fmt.Sprint("Keyvalues must appear in pairs: ", keyvals))
		return nil
	}
	var data []zap.Field
	for i := 0; i < len(keyvals); i += 2 {
		data = append(data, zap.Any(fmt.Sprint(keyvals[i]), fmt.Sprint(keyvals[i+1])))
	}
	switch level {
	case log.LevelDebug:
		l.log.Debug("", data...)
	case log.LevelInfo:
		l.log.Info("", data...)
	case log.LevelWarn:
		l.log.Warn("", data...)
	case log.LevelError:
		l.log.Error("", data...)
	}
	return nil
}

其中通过 rotatelogs 进行日志文件的滚动

读取配置文件

Kratos的config组件可以很方便的从各种配置源加载配置;比如从文件中读取:

path := "configs/config.yaml"
c := config.New(
    config.WithSource(
        file.NewSource(path),
    )

因为之前接收参数是分别接收了本地配置文件和consul远程配置参数;对应的将这两种读取配置的方式做一下封装。

// getConfigKey 获取合法的配置名
func getConfigKey(configKey string, useBackslash bool) string {
	if useBackslash {
		return strings.Replace(configKey, `.`, `/`, -1)
	} else {
		return configKey
	}
}

// NewConsulConfigSource 创建一个远程配置源 - Consul
func NewConsulConfigSource(configHost, configKey string) config.Source {
	consulClient, err := api.NewClient(&api.Config{
		Address: configHost,
	})
	if err != nil {
		panic(err)
	}
	consulSource, err := consulKratos.New(consulClient,
		consulKratos.WithPath(getConfigKey(configKey, true)),
	)
	if err != nil {
		panic(err)
	}

	return consulSource
}

// NewFileConfigSource 创建一个本地文件配置源
func NewFileConfigSource(filePath string) config.Source {
	return file.NewSource(filePath)
}
如有疑问关注公众号给我留言
wx

关注公众号领取Go学习资料

wx

洋葱小店

©2017-2023 鲁ICP备17023316号-1 Powered by Hugo