追記
リファクタリングに gofmt だけでなく gorename も使えるようになりました.単なる文字列の置き換えではうまくいかない場合は gorename を使おう!
@mattnさんの記事
golang のリファクタリングには gofmt ではなく、gorename を使おう。
概要
golang のリファクタリングは面倒と思いませんか?たとえば,public なメソッドを private にしようと思ったら,該当メソッドの頭文字を大文字から小文字に変更しなきゃいけなくて,いっぱい編集箇所があって泣けるとかありませんか?
なんでこんなに面倒なんだ!と思っていましたが,さすが golang.すでにリファクタリング用のツールが用意されていました.それも,普段よく使う gofmt がそれでした.
gofmt をリファクタリングに使う
出典:https://golang.org/cmd/gofmt/
こちらをあたっていただくのが間違いないです.
使い方
flag のところに下記に示すオプションを指定して,pathのとこに golang のファイルを指定します.
gofmt [flags] [path ...]
普段使ってる go fmt
は,gofmt -l -w
と同じです.
オプション
flag | 説明 |
---|---|
-d |
フォーマッタを適用した場合の差分だけを表示 |
-e |
エラーをすべて表示(表示にはエラーとして間違っているものも含むかもしれない) |
-l |
フォーマットの対象となるファイル名だけを表示 |
-r rule |
指定されたルールを適用した場合のコードを表示(ファイルは書き換わらない) |
-s |
コードをシンプルにした結果表示 |
-w |
フォーマットの対象となったファイルを上書き |
例
% gofmt -d foo.go
diff da.go gofmt/da.go
--- /tmp/gofmt443368917 2014-09-04 17:00:11.000000000 +0900
+++ /tmp/gofmt933503792 2014-09-04 17:00:11.000000000 +0900
@@ -1,8 +1,8 @@
package foo
import (
-"fmt"
-"sort"
+ "fmt"
+ "sort"
)
% gofmt -l foo.go
foo.go
リファクタリング
-r
オプションをつけて,引数に
pattern -> replacement
の形で変換を指定します.基本的には単純な置き換えです.ただし,小文字一文字は任意の要素にマッチするワイルドカードとして使えます.例えば,配列の record[0:len(records)]
を records[0:]
に置き換えるには,a[b:len(a)] -> a[b:]
と指定します.
% gofmt -r 'a[b:len(a)] -> a[b:]' -d foo.go
diff foo.go gofmt/foo.go
--- /tmp/gofmt374308561 2014-09-04 17:43:33.000000000 +0900
+++ /tmp/gofmt670076412 2014-09-04 17:43:33.000000000 +0900
@@ -21,7 +21,7 @@
{ID: 22, Name: "orange"},
}
- for i, _ := range records[0:len(records)] {
+ for i, _ := range records[0:] {
fmt.Printf("id: %d, name: %s", r.ID, r.Name)
}
fmt.Println(records[0].ID, fruite[0].ID)
基本的には,単純な置き換えなので,違う構造体のメンバで同じ名前があったり,変数で同じ名前があったりすると,全部変換されちゃいます.
% gofmt -r 'ID -> Hoge' -d foo.go
diff foo.go gofmt/foo.go
--- /tmp/gofmt984846593 2014-09-04 17:53:09.000000000 +0900
+++ /tmp/gofmt966547564 2014-09-04 17:53:09.000000000 +0900
@@ -1,31 +1,31 @@
package foo
type Record struct {
- ID int
+ Hoge int
Name string
}
type Fruite struct {
- ID int
+ Hoge int
Name string
}
func main() {
records := []Record{
- Record{ID: 1, Name: "johon"},
- Record{ID: 2, Name: "robert"},
+ Record{Hoge: 1, Name: "johon"},
+ Record{Hoge: 2, Name: "robert"},
}
fruites := []Fruites{
- {ID: 11, Name: "apple"},
- {ID: 22, Name: "orange"},
+ {Hoge: 11, Name: "apple"},
+ {Hoge: 22, Name: "orange"},
}
for i, _ := range records[0:len(records)] {
- fmt.Printf("id: %d, name: %s", r.ID, r.Name)
+ fmt.Printf("id: %d, name: %s", r.Hoge, r.Name)
}
- fmt.Println(records[0].ID, fruite[0].ID)
+ fmt.Println(records[0].Hoge, fruite[0].Hoge)
- var ID = 1
- fmt.Println(ID)
+ var Hoge = 1
+ fmt.Println(Hoge)
}
メンバだけ変換したいなら,a.ID -> a.Hoge
とかするしかないようです.でも,これだけだと,構造体の定義は書き換わらないので注意が必要です.
この辺,上手くやる方法をご存じの方いらっしゃればお教えください
あとがき
golint というのもあるので,コードチェックしながらリファクタリングすると golang っぽいコードになるのかなと思いました.とはいえ,なんかちょっと不便なので vim なり emacs なり eclipse なりで簡単にできるならそれがいいので教えてください