golangでコマンドラインツールを作る #8 ディレクトリを分けてリファクタする

f:id:masato47744:20150816150451p:plain

その7の続き

パッケージの分けかた

ファイル分けて処理を関数色々書いたけど、同じ名前にするとduplicateになる。 goの場合はpackageという概念があって、その中では同じ定義になるようだ。

ということで、別パッケージに分けようとしたら、そんなパッケージ見つからないよと言われた。 やったのは、普通にpbxprojっていうディレクトリ作って、その下にpbxproj.goを作って、package pbxprojって先頭にいれておく。 それで、他のファイルで、import "pbxproj"ってやった。

軽くググってみると外部に公開しないようなpackageはinternalってやつがGo1.4から導入されてmainのGoのpackageについては適用されるみたいな記事を見つけた。

golang - go1.4で追加されたinternal packageについて - Qiita

ただ、サブパッケージとか色々ググってたり、他のプロジェクト見てたら自分が間違ってることに気づいた。importするときに、"github.com/mpon/xgodeproj/pbxproj" みたいに github.comから始めないといけないようだ。 じゃあ、さっきのinternalってやつはなんなんだろうか。まぁ今は深追いはやめておこう。

structにメソッドを所属させる

packageは分けれたけど、インスタンス作成して、そいつに対してメソッドを呼び出していくみたいのやりたい。 structにメソッドを生やせるみたいのあったのを思い出した。これが参考になりそう。2年前だけど。

Go の interface 設計 - Block Rockin’ Codes

そして、structにコンストラクタもたせる方法。

golang - Goで見かける構造体パターン - Qiita

staticなfunctionとか作りたくなったりするけど、今はとりあえずutil.goっての作ってそこにfuncを定義しておいた。

これで、結構コマンドライン側のファイルからproject.pbxprojをパースするあたりを切り出せた。 pbxprojに、project.pbxprojのパスを渡すと、jsonとかパースしてそのインスタンスがデータを 持っておいてくれるみたいな感じ。golangではインスタンスっていっちゃいけないのかも。

// CmdShow for print sections
func CmdShow(c *cli.Context) {

    // find project.pbxproj path
    proj, found := findProjectPath()
    if !found {
        fmt.Println("Not found project.pbxproj file.")
        return
    }

    // get flags
    section := c.String("section")
    isSectionNotSet := section == ""

    // parse pbxproj
    pbxproj := pbxproj.NewPbxproj(proj)

略

ここまでの感想

  • packageの考え方が少しずつ分かってきた
  • structとstructにメソッドを所属させるところも分かってきた
  • internal packageってなんに使うんだろう?
  • static な func作りたくなった時はどうするのが正しいのか、そもそもそんなことしちゃいけない?
  • ClassとかOOPな考え方しかできなくてGoっぽい頭になるにはまだまだダメって感じ
  • Goやるならinterfaceをちゃんと使っていかないとダメっぽそう

その9