Help us understand the problem. What is going on with this article?

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

More than 5 years have passed since last update.

追記

リファクタリングに 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:

ikawaha
形式言語理論・オートマトン / 正規表現エンジン,キーワードフィルタ,係り受け解析,固有表現抽出 / 押してだめならふて寝しろ
http://ikawaha.hateblo.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした