LoginSignup
57
48

More than 5 years have passed since last update.

golang のリファクタリングには gofmt が使える

Last updated at Posted at 2014-09-04

追記

リファクタリングに 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 なりで簡単にできるならそれがいいので教えてください :bow:

57
48
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
57
48