Go Modulesのreplaceでforkしたコードのimportを書き換えずにfork後のpackageに向ける

golang

Goはimportの際に相対パスやモジュール名ではなくgithub.com/foo/barのようなフルパスで指定するため、forkしたコードを使うと参照するpackageは元のままになってしまう。Go Modulesのreplace directiveを使うとコードを書き換えずに依存先を変えることができる。相対パスも使える。

When should I use the replace directive? · golang/go Wiki · GitHub

module example.com/me/hello

require (
    example.com/foo/bar v0.0.0
)

replace (
    example.com/foo/bar/aaa => ./
    example.com/foo/bar/bbb => example.com/hoge/bar/bbb v1.0.0
)

fork元のmodule。文字列を出力するだけのもの。

$ cat go-something/lib/lib.go 
package lib

import "fmt"

func Do() {
	fmt.Println("this is original")
}

$ cat go-something/main.go 
package main

import "github.com/sambaiz/go-something/lib"

func main() {
	lib.Do()
}

$ go run go-something/main.go 
this is original

fork先のmodule。出力する文字列を変えている。

$ cat go-something-fork/lib/lib.go 
package lib

import "fmt"

func Do() {
	fmt.Println("this is fork") // edit
}

しかし、これを実行すると元々の文字列が出力されてしまう。

$ cat go-something-fork/go.mod 
module github.com/sambaiz/go-something-fork

go 1.13

require github.com/sambaiz/go-something v0.0.0-20200301104436-97bba924e129

$ go run go-something-fork/main.go 
this is original

replaceを追加して実行すると文字列が変わり、fork先のpackageをimportしていることが確認できる。

$ cat go-something-fork/go.mod 
module github.com/sambaiz/go-something-fork

go 1.13

require github.com/sambaiz/go-something v0.0.0-00010101000000-000000000000

replace github.com/sambaiz/go-something => ./

$ go run go-something-fork/main.go 
this is fork