The basic use

The main is to read and write configuration files, and convenient library, should be said to be the most mature go language in a configuration program github.com/spf13/viper

The only thing to note is that the vipe Settings are prioritized, and the keys set are case insensitive

We can simply configure a file:

Simple use:

func main() { viper.Set("fileDr", "./") // Read configuration file viper.setConfigname ("config") // Name of configuration file viper.setConfigType ("json") // Extension of configuration file, // This configuration can be multiple, Err := per.readinConfig () if err! = nil { panic(err) } fmt.Println(viper.Get("name")) }Copy the code

In addition to reading configuration files we can of course write configuration files

viper.Set("age", "181")
viper.WriteConfigAs("config.json")
Copy the code

You can also monitor configuration file changes:

viper.WatchConfig()
viper.OnConfigChange(func(in fsnotify.Event) {
   fmt.Println("config changed",in.name)
})
Copy the code

In addition, Viper can also support remote reading of configuration information such as etCD configuration information

Viper also supports access to environment variables. If you are interested, read the documentation. I don’t like to manipulate environment variables. So here we go again

Viper Points to note when reading values

Unconfigured returns 0, so we usually use isSet

if ! viper.IsSet("house") { fmt.Println("no house key") }Copy the code

Nested keys can be delimited with

fmt.Println(viper.Get("address.location"))
Copy the code

It can also be serialized directly

Json form such as:

{" age ":" 181 ", "name" : "wuyue", "address" : {" location ":" nanjing "}}Copy the code

Defining structure

type Config struct {
   Age     string `json:"age"`
   Name    string `json:"name"`
   Address struct {
      Location string `json:"location"`
   } `json:"address"`
}
Copy the code
var config Config
viper.Unmarshal(&config)
Copy the code

Of course, this structure can also be defined by mapStructure

type Config2 struct {
   Age     int
   Name    string
   Address `mapstructure:"address"`
}

type Address struct {
   Location string
}
Copy the code

Graceful shutdown and restart

When our Web service application needs to be updated, we usually kill the process and restart it. But that’s a little rude, because suppose you kill the process. When a request comes in and the process is killed, the initiator of the request has a bad experience.

Ideally, we can kill the Web process and the Web service can do all the work on the phone (the request has been connected, but the application is still executing and there is no response) and then kill itself.

func main() { router := gin.Default() router.GET("/", func(context *gin.Context) { time.Sleep(5 * time.Second) context.String(http.StatusOK, "welcome to gin server") }) srv := &http.Server{ Addr: ":8080", Handler: router, } go func() { err := srv.ListenAndServe() if err ! = nil {fmt.println (err)}}() // Wait for an interrupt Signal to shut down the server quit := make(chan os.signal, 1) // Kill -2 is the SIGINT signal that triggers the system // Kill -9 is the sigkill signal that triggers the system. SIGINT SIGTERM (quit signal. notify (quit, syscall.sigint, syscall.sigint, syscall.sigint, syscall.sigint, syscall.sigint, syscall.sigint, <-quit log.Println("shutdown server") // Create a context CTX that timed out for 5 seconds, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := srv.Shutdown(ctx); err ! = nil { log.Fatal("server shutdown ") } }Copy the code

Experiment is also very good, we in the browser to access a web connection, gin code at this time, we set up to 5 seconds later to return, then we CTRL c kill off the process You will find that, the program is not die immediately, but when after response would kill off his browser can normally get the response

Nor is it difficult to reboot gracefully

The principle is that when we receive a signal, we fork out a child, and the parent process does whatever it needs to do. New requests are sent to the child process, and the parent process finishes its work

If you are interested, you can see github.com/fvbock/endl…

Note that if you use a process management tool like Supervisor, you don’t need to do a graceful restart, just a little attention to a graceful shutdown