1. Why use global Starter
When working with Golang as a project, you often need to hard-code framework configurations in your program, such as the startup port number for IRIS, the connection IP and link parameter protocol for mysql, the configuration of the logging framework, and so on.
Hard-coded configurations can be difficult to replace and manage, and the code can be jumbled.
Therefore, you can use the global unified configuration (Application.properties) and Starter development mode similar to Java SpringBoot, and the configuration is defined in the configuration file, different framework configuration code is managed by different Starter.
Techniques used:
- Go Mod (version management)
- Viper (Configuration Management)
Second, global Starter code implementation
2.1 Scaffold project structure
2.2 Specific code
- main/main.go
package main
import (
"github.com/spf13/viper"
"golang-starter-project/src/infra"
// Triggers the global init function
_ "golang-starter-project/src"
)
// Global Starter to configure the Starter and start the project
func main(a) {
// Get the global configuration file
conf := getConfig()
app := infra.NewBootApplication(conf)
app.Run()
select{}}func getConfig(a) *viper.Viper {
conf := viper.New()
conf.SetConfigName("config")
conf.SetConfigType("yaml")
conf.AddConfigPath("./src/main/")
err := conf.ReadInConfig()
iferr ! =nil {
panic(err)
}
return conf
}
Copy the code
- main/config.yaml
server:
name: golang-starter-demo
port: 8804
enable: true
Copy the code
- src/app.go
package src
import (
"golang-starter-project/src/infra"
"golang-starter-project/src/infra/starters"
)
// Preload all Starter containers
func init(a) {
infra.Register(&starters.LogStarter{})
}
Copy the code
- infra/starter.go
package infra
import "github.com/spf13/viper"
// The Starter interface, which defines the basic Starter methods
type Starter interface {
// Initialize the Starter configuration
Init(conf *viper.Viper)
// Configure the Starter parameters
Setup(conf *viper.Viper)
/ / start the Starter
Start(conf *viper.Viper)
}
// BaseStarter, default empty implementation of the Starter interface
var _ Starter = new(BaseStarter)
type BaseStarter struct{}
func (b *BaseStarter) Init(conf *viper.Viper) {}
func (b *BaseStarter) Setup(conf *viper.Viper) {}
func (b *BaseStarter) Start(conf *viper.Viper) {}
// The Starter registry, which holds all Starter instances, global singletons
type starterRegister struct {
starters []Starter
}
var register = new(starterRegister)
/ / get starterRegister
func StarterRegister(a) *starterRegister {
return register
}
/ / register the Starter
func (s *starterRegister) register(starter Starter) {
s.starters = append(s.starters, starter)
}
// Obtain all registered Starters
func (s *starterRegister) allStarters(a) []Starter {
return s.starters
}
func Register(starter Starter) {
register.register(starter)
}
func AllStarters(a) []Starter {
return register.allStarters()
}
Copy the code
- infra/boot.go
package infra
import "github.com/spf13/viper"
// Global Starter configuration and initiators, global singleton
type bootApplication struct {
conf *viper.Viper
}
var conf *viper.Viper
// Pass in the global configuration file conf and get bootApplication
func NewBootApplication(vipConf *viper.Viper) *bootApplication {
if vipConf == nil {
panic("conf is nil")
}
conf = vipConf
application := &bootApplication{conf: vipConf}
return application
}
// Get the global configuration file
func Conf(a) *viper.Viper {
if conf == nil {
panic("conf is nil")}return conf
}
// Start the bootApplication and initialize the Starter
func (b *bootApplication) Run(a) {
/ / initialization
initStarters()
/ / configuration
setupStarters()
/ / start
startStarters()
}
func startStarters(a) {
for _, s := range AllStarters() {
s.Start(conf)
}
}
func setupStarters(a) {
for _, s := range AllStarters() {
s.Setup(conf)
}
}
func initStarters(a) {
for _, s := range AllStarters() {
s.Init(conf)
}
}
Copy the code
- starters/logrus_starter.go
package starters
import (
"github.com/sirupsen/logrus"
"github.com/spf13/viper"
prefixed "github.com/x-cray/logrus-prefixed-formatter"
"golang-starter-project/src/infra"
"os"
)
/ / implementation BaseStarter
type LogStarter struct {
infra.BaseStarter
}
func (l *LogStarter) Setup(conf *viper.Viper) {
// Define the log format
formatter := &prefixed.TextFormatter{}
// Enable full timestamp output and timestamp format
formatter.FullTimestamp = true
formatter.TimestampFormat = "The 2006-01-02. 15:04:05. 000000"
// The console is highlighted
formatter.ForceFormatting = true
formatter.ForceColors = true
formatter.DisableColors = false
// Set the color style for the highlight
formatter.SetColorScheme(&prefixed.ColorScheme{
InfoLevelStyle: "green",
WarnLevelStyle: "yellow",
ErrorLevelStyle: "red",
FatalLevelStyle: "41",
PanicLevelStyle: "41",
DebugLevelStyle: "blue",
PrefixStyle: "cyan",
TimestampStyle: "37",
})
logrus.SetFormatter(formatter)
// The log level is set by the environment variable
// You can change it to the configuration later
level := os.Getenv("log.debug")
if level == "true" {
logrus.SetLevel(logrus.DebugLevel)
}
logrus.Info("Test log starter [1]")
logrus.Debug("Test log starter [2]")}Copy the code
Three, the realization of logical sequence diagram
Github address
Github.com/pbrong/gola…