开发中,我们会遇到批量加入或者替换某一些代码的场景,可以使用 uber gopatch

举个栗子

  1. 比如在下面的代码里,有开协程的代码块,但是没有加recover 功能,需要一个一个向每个文件加入太麻烦。今天的主角gopatch就可以解决这类问题。

以code目录下有 a.go 和b.go 文件为例

//A a.go
func A() {
    // ...
    fmt.Println(`A function`)
    go func() {
        fmt.Println(`A goroutine`)
    }()
    //...
}
//B b.go
func B() {
    // ...
    fmt.Println(`B function`)
    go func() {
        fmt.Println(`B goroutine`)
    }()
    //...
}

我们想要达到下面这种效果


//A a.go
import (
"fmt"
"log"
"runtime/debug"
)

func A() {
// ...
fmt.Println(`A function`)
go func() {
  defer func() {
    if err := recover(); err != nil {
      log.Printf("{{ FileName }} recover from panic, err=%+v, stack=%v", err, string(debug.Stack()))
    }
  }()
log.Flags()
fmt.Println(`A goroutine`)
}()
//...

}
------

//B b.go
import (
"fmt"
"log"
"runtime/debug"
)
func B() {
// ...
fmt.Println(`B function`)
go func() {
  defer func() {
  if err := recover(); err != nil {
    log.Printf("{{ FileName }} recover from panic, err=%+v, stack=%v", err, string(debug.Stack()))
  }
}()
fmt.Println(`B goroutine`)
}()
//...
}

首先我们需要写patch 文件,命名为 recover.patch
内容如下

@@
@@
+ import "runtime/debug"
+ import "log"

go func(...) {
+    defer func(){
+        if err := recover(); err != nil {
+            log.Printf("{{ FileName }} recover from panic, err=%+v, stack=%v", err, string(debug.Stack()))
+        }
+    }()
  ...
}()

接下来,我们就能执行命令了

gopatch -p ./recover.patch ./code/...

命令中的 ./... 有关说明可以看 golang ... 之 ./...

再去看一下go文件。就达到我们批量加入的需求了。