SoFunction
Updated on 2025-03-01

Automatic restart method in golang API development process (based on gin framework)

summary

When developing web services based on the golang Gin framework, you need to build them from time to time, and then restart the service to view the running results.
The go build process is integrated in the editor (emacs) and can be completed quickly through shortcut keys, but every time the service is restarted, it switches to the command line to operate.
Therefore, it is hoped that the service can be automatically restarted after the compilation is passed.

This is not a service restart during the deployment stage, so don't worry too much about whether to exit the coroutines normally.

Implementation method

In open sourceilluminantIn the project, the corresponding code has been integrated into the debug mode of gin.

Code File:/wangyubin/illuminant/blob/dev/server_cmd.go

 func setupWatcher() (chan struct{}, error) {
  file, err := ()
   if err != nil {
   return nil, err
   }
  ("watching %q\n", file)
   w, err := ()
   if err != nil {
   return nil, err
  }
  done := make(chan struct{})
  go func() {
   select {
   case e := <-:
    ("watcher received: %+v", e)
    err := (file, , ())
    if err != nil {
     (err)
    }
   case err := <-:
    ("watcher error: %+v", err)
   case <-done:
    ("watcher shutting down")
    return
   }
  }()
  err = (file)
  if err != nil {
   return nil, err
  }
  return done, nil
 }

Under gin debug mode, use this method to automatically restart the service

if ("prod") {
   ()
   // start route
   return ()
  } else {
   ()
   watcher, err := setupWatcher()
   if err != nil {
    // do something sensible
   (err)
  }
  defer close(watcher)
  return ()
 }

Replenish

The core of the above function has the following two points:

  • w, err := (): Create a watcher that monitors file changes, err = (file) and add the current binary file to the monitoring file list
  • err := (file, , ()) When accepting an event of a file change, call yourself again and use the same parameters and environment variables as last time

For this function, it may be used less often. Here is a brief introduction. It has 3 parameters:

  • args[0]: The path to the executable file (relative path, absolute path or path in PATH is OK)
  • args[1]: Command parameters
  • args[2]: The environment variable for the execution of the command, () represents the environment variable inheriting the caller

When executed, all unexecuted programs before it will be aborted (including programs executed in go routine),
Then execute the called command, which remains executed under the PID of the previous program.

It is the last code to be executed. After restarting, there can be code after it, but none of it will be executed, including the code in defer.

Here is a small example (this example can verify the above conclusion):

package main
  
  import (
  "fmt"
  "log"
  "os"
  "syscall"
  "time"
  
  "/fsnotify/fsnotify"
  "/kardianos/osext"
 )
 
 func syscallExec() {
  watcher, err := setupWatcher()
  if err != nil {
   (err)
  }
  defer finally(watcher)
 
  ("current pid: %d\n", ())
  var count = 0
 
  go func(count int) {
   for {
    ("&gt;&gt;&gt; count in GO ROUTINE: %d\n", count)
    count++
    (1 * )
   }
  }(count)
 
  for {
   ("&gt;&gt;&gt; count in MAIN: %d\n", count)
   count++
   (1 * )
  }
 }
 
 func finally(watcher chan struct{}) {
  // This function is not executed during restart  ("exit original exec")
  close(watcher)
 }
 
 func setupWatcher() (chan struct{}, error) {
  file, err := ()
  if err != nil {
   return nil, err
  }
  ("watching %q\n", file)
  w, err := ()
  if err != nil {
   return nil, err
  }
  done := make(chan struct{})
  go func() {
   select {
   case e := &lt;-:
    ("watcher received: %v", e)
    err := (file, , ())
    if err != nil {
     (err)
    }
   case err := &lt;-:
    ("watcher error: %+v", err)
   case &lt;-done:
    ("watcher shutting down")
    return
   }
  }()
  err = (file)
  if err != nil {
   return nil, err
  }
  return done, nil
 }

This is the article about the automatic restart method (based on the gin framework) in the golang API development process. For more related golang API automatic restart content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!