[Code articles] Build your own golang framework step by step from scratch (3)

In the last article, we set the basic directory structure of the project. Now let ’s review my thinking:

  1. Create an entry file;
  2. Specify configuration, log directory;
  3. Specify the database, queue, cache component directory;
  4. Create a controller directory for data processing;
  5. Specify miscellaneous items such as public functions.

Next, we still fill the code in this order.

Entry file

func main()  {
    config.InitConfig()
    logger.InitLogger()
}

Ignoring some implementation details for the time being, we need to initialize the configuration and logs first. Let's take a look at the logs first. I chose Uber's zap log library. Let's see how to write the log module?

Log

package logger

import (
    "go.uber.org/zap"
    "go.uber.org/zap/zapcore"
    "gopkg.in/natefinch/lumberjack.v2"
)

var l *zap.Logger

func InitLogger(logPath, logLevel string) error {
    hook := lumberjack.Logger{
        Filename:   logPath,
        MaxSize:    1024,
        MaxBackups: 3,
        MaxAge:     7,
        Compress:   true,
    }
    w := zapcore.AddSync(&hook)

    var level zapcore.Level
    switch logLevel {
    case "debug":
        level = zap.DebugLevel
    case "info":
        level = zap.InfoLevel
    case "error":
        level = zap.ErrorLevel
    default:
        level = zap.DebugLevel
    }

    encoderConfig := zap.NewProductionEncoderConfig()
    encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
    core := zapcore.NewCore(
        zapcore.NewConsoleEncoder(encoderConfig),
        w,
        level,
    )

    l = zap.New(core)

    return nil
}

func GetLogger() *zap.Logger {
    return l
}

We first define a package-level global variable l of type * zap.Logger, and create two functions, InitLogger and GetLogger. Because zap does not support log archiving, a lumberjack hook is defined in InitLogger to archive logs. We can see that the InitLogger method has two input parameters: logPath and logLevel. Generally speaking, these parameters should be placed in the configuration file, then we will write the configuration.

Configuration

We simply create a config.json file to store the configuration:
config.json:

{
  "log_config": {
    "log_path": "{your_path}",
    "log_level": "debug"
  }
}

Then create the corresponding structure in config.go, and then define the InitConfig and GetConfig methods. In the InitConfig method, I read the content of the configuration file, then parse it into the structure, and handle the error, if there is an error message , I will wrap the error message in one layer to facilitate future error location. InitConfig has an input parameter, which is the path of the configuration file. I will get this parameter from the command line.
config.go:

package config

import (
    "encoding/json"
    "github.com/pkg/errors"
    "io/ioutil"
)

type LogConfig struct {
    LogPath string `json:"log_path"`
    LogLevel string `json:"log_level"`
}

type Config struct {
    LogConfig LogConfig `json:"log_config"`
} 

var conf Config

func InitConfig(configPath string) error {
    configFile, err := ioutil.ReadFile(configPath)
    if err != nil {
        err = errors.Wrap(err, "Read config file failed.")
        return err
    }
    err = json.Unmarshal(configFile, &conf)
    if err != nil {
        err = errors.Wrap(err, "Unmarshal config file failed.")
        return err
    }
    return nil
}

func GetConfig() Config {
    return conf
}

Of course, we have more than this configuration. We also have database, cache and other configurations not added, but not in a hurry, we first figure out a route, and the subsequent configuration can be painted according to the gourd.

Adjust entry file

Ok, the initialization of the log and configuration is roughly written, let's go back and look at the adjustment of the entry file:

package main

import (
    "flag"
    "fmt"
    "github.com/TomatoMr/awesomeframework/config"
    "github.com/TomatoMr/awesomeframework/logger"
    "os"
)

func main()  {
    var configPath string
    flag.StringVar(&configPath, "config", "", "配置文件路径")
    flag.Parse()

    if configPath == "" {
        fmt.Printf("Config Path must be assigned.")
        os.Exit(1)
    }

    var err error
    err = config.InitConfig(configPath)
    if err != nil {
        fmt.Printf("Init config failed. Error is %v", err)
        os.Exit(1)
    }

    logConfig := config.GetConfig().LogConfig

    err = logger.InitLogger(logConfig.LogPath, logConfig.LogLevel)
    if err != nil {
        fmt.Printf("Init logger failed. Error is %v", err)
        os.Exit(1)
    }
    
    logger.GetLogger().Info("Init success.")
}

We adjusted the entry file, obtained the configuration file path from the command line, then initialized the configuration and logs, and finally printed the initialization result.

have a test

First, compile:

$ go build 

Then modify the log_path of your config.json file, and then specify the path of your configuration file on the command line:

$ awesomeframework --config={$your_path}/config.json

Finally, take a look at the operation is not normal, the log file is printed as follows:

2020-01-19T20:41:57.506+0800	info	Init success.

summary

So far, we have initialized the configuration and logs, and then we will start to initialize the database and other components. The code for today can be found at https://github.com/TomatoMr/awesomeframework
. To be continued ...


Welcome to pay attention to my public number: onepunchgo.

image

Published 20 original articles · Likes0 · Visits 768

Guess you like

Origin blog.csdn.net/qq_31362439/article/details/104049169