思路是监听.go文件变化,然后重启进程即可。
example.go
package main
import (
"flag"
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
"github.com/fsnotify/fsnotify"
)
func buildServer(target string) string {
binPath, err1 := exec.LookPath("go")
if err1 != nil {
fmt.Println("Cannot find go executable file", err1)
os.Exit(-2)
}
outputName := ""
if target == "." {
outputName = "project.bin"
} else if strings.HasSuffix(target, ".go") {
outputName = strings.Split(target, ".")[0]
} else {
fmt.Println("taget must: '.' or '*.go' ", err1)
os.Exit(-2)
}
// pwd, _ := os.Getwd()
args := []string{"go", "build", "-o", outputName, target}
procAttr := &os.ProcAttr{
Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
}
process, err := os.StartProcess(binPath, args, procAttr)
if err != nil {
fmt.Println(err)
}
fmt.Println(args, "executing")
process.Wait()
fmt.Printf("Build %s success\n", outputName)
return outputName
}
func createProcess(target string) (*os.Process, string) {
outputName := buildServer(target)
binPath, err1 := exec.LookPath("./" + outputName)
if err1 != nil {
fmt.Printf("Cannot find %s executable file\n", outputName)
os.Exit(-3)
}
// pwd, _ := os.Getwd()
args := []string{binPath}
procAttr := &os.ProcAttr{
Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
}
process, err := os.StartProcess(outputName, args, procAttr)
if err != nil {
fmt.Println(err)
os.Exit(-4)
}
return process, outputName
}
func main() {
target := flag.String("start", ".", "go build && run it")
flag.Parse()
process, outputName := createProcess(*target)
fmt.Printf("Running %s PID: %d\n", outputName, process.Pid)
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Fatal(err)
}
defer watcher.Close()
done := make(chan bool)
lastModify := time.Now().Unix()
go func() {
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
log.Println("event:", event)
if event.Op&fsnotify.Write == fsnotify.Write {
if strings.HasSuffix(event.Name, ".go") {
if time.Now().Unix()-lastModify > 3 {
lastModify = time.Now().Unix()
err := process.Kill()
if err != nil {
fmt.Println(err)
os.Exit(-1)
} else {
fmt.Println("Restarting...")
process, outputName = createProcess(*target)
}
} else {
fmt.Println("Update too full, ignored", process.Pid)
}
}
}
case err, ok := <-watcher.Errors:
if !ok {
return
}
log.Println("error:", err)
}
}
}()
e := filepath.Walk("./", func(path string, f os.FileInfo, err error) error {
if f == nil {
return err
}
if f.IsDir() {
err = watcher.Add(path)
log.Printf("Dir:%s add to watch", path)
if err != nil {
log.Fatal(err)
}
}
return nil
})
if e != nil {
fmt.Printf("filepath.Walk() returned %v\n", err)
}
<-done
}
运行
go run example.go -start gin.go
网友评论