LoginSignup
20

More than 5 years have passed since last update.

Go言語入門 パッケージの作成、便利ツール、interfaceとは。

Last updated at Posted at 2015-12-07

概要

「ツイートのIDがわかっていてツイートのテキストを取得したい」という状況があり、
Twitter APIでは制限が 180GET/15minutes で遅かったので、
URLからHTMLをとってきてパースする単純なGoコードを書いたのですが、
リポジトリを作ってパッケージ化してしまおうかなと思った次第です。

パッケージの作成を通して自分が使っている便利ツールを紹介したいと思います。
また、コメントで他の開発便利ツール教えていただけたら嬉しいです。

Go言語について

Goは開発支援ツールが充実している気がします。気がします。

あとは、ここでは触れませんがchannelを使うと並行処理が割と簡単にできます。
(例えば、500個のツイートを取得するために、100個のループ5つを並列に回したり。)
あと、入門系記事にあんまり書いてありませんが、便利なのが構造体のタグです。
(jsonのキー名決めたり、ORMのカラムの型決めたりする時。reflectで取れる。)

パッケージ作成

大まかな仕様

  • APIでデータを取得する方法は考慮しない
  • 取得したいツイートのURLは既知
  • エラーを拡張して何によるエラーなのか分類
  • HTML内に含まれる(一連の会話)リプライも取得

手順

  1. リポジトリ作成
  2. ファイル作成
  3. テストコード
  4. ソースコード
  5. ドキュメント

リポジトリ作成

リポジトリを作ります。
GoDocGo SearchGitHubで検索してみます。

simpletwitterなるものをGitHubで作りました。(.gitignoreとかはGitHubGo指定して自動生成してもらいました。)
GitHubとかじゃないプライベートリポジトリの場合、URL的に色々障壁があるみたいです。

最初はまだ何もソースがないので -d オプションつけて get してください。

go get -d github.com/sosuke-k/simpletwitter

ファイル作成

ファイル名はパッケージフォルダ直下にあれば何でもいいですがとりあえず tweet.goを作成しました。パッケーシ名はsimpletwitterにしました。

【便利ツールその1】goimports

goimports - The Go Programming Language

https://gyazo.com/ce65179cadd9a58efc07f3f64a364026

Goの書式を修正してくれるツールにgofmtがありますが、goimports は更に使われているパッケージのimportまで自動で付加してソートしてくれます。(使われてないものが消されてしまいます。)
命名規則にあってないものや、パッケージ外から使える関数(大文字から始まる)などを定義した時に説明コメントがないものなど、色々警告してくれます。

go get code.google.com/p/go.tools/cmd/goimports

で使えます。

atomユーザはgo-plusを入れることで保存時に実行してくれます。

テストコード

testing - The Go Programming Language

create a file whose name ends _test.go that contains the TestXxx functions as described here

ので、tweet_test.goを作りました。

assert

こちらで言われていますが、

Go には標準 assert がない

思想なのでしょうが、、、自分は特にこだわりません。自分の置かれている環境で便利な方がいいです汗

【便利ツールその2】goconvey

GoConvey - Go testing in the browser

it's more expressive than t.Errorf()

はい :raised_hand: そっちがいいです。イントロビデオがあるので、最初の方だけでも見ると雰囲気わかります。

go get github.com/smartystreets/goconvey
cd $GOPATH/github.com/sosuke-k/simpletwitter
goconvey

goconveyコマンドを実行するとブラウザが開きます。

https://gyazo.com/011f0058cd178f8f0c057bb19bbf4c64

テーマを変更したり、デバグ出力の切り替えや監視フォルダを指定したりできます。
最初はgoconveyを実行したディレクトリが監視フォルダになっています。

上書き保存すると自動でテストを実行し結果をブラウザ上に表示してくれるので、シンプルなエディターを使っていてマルチディスプレイとかだとめちゃくちゃ捗りますし、かっこいいです。

Composer

tweet.go
func NewTweet(url string) (tweet Tweet, err error) {
    return
}

上のような関数のテストを書きたい時に、下図左のようなテキストを入力すると下図右のような雛形を出力してくれます。

https://gyazo.com/61bd2be596e247ac701ca40c9f3aade1

Composerは正直、あまり使わないです。。。

Conveyテストコード

基本的にConvey関数の3つ目の引数に無名関数でテスト書きます。

先ほどの雛形をtweet_test.goに貼り付けると以下のような出力に変わります。

https://gyazo.com/fca1c3eb64a61c97f1a04f075046676f

以下のようなテストにすると

tweet_test.go
func TestNewTweet(t *testing.T) {
    Convey("Given available first post tweet url\n", t, func() {
        url := "https://twitter.com/olha_drm/status/418033807850496002"
        tweet, err := simpletwitter.NewTweet(url)

        So(err, ShouldEqual, nil)
        So(tweet.Text, ShouldEqual, "よるほ あけましておめでとうございますほー")
        So(tweet.ScreenName, ShouldEqual, "olha_drm")
        So(tweet.Name, ShouldEqual, "織羽")
        So(len(tweet.After), ShouldEqual, 1)
        So(tweet.After[0].Text, ShouldEqual, "@olha_drm あけおめっ!ことよろー!!")
        So(tweet.After[0].ScreenName, ShouldEqual, "reprohonmono")
    })
}

こんな感じ。

https://gyazo.com/a3f73c88d9ac0d6250f608f70067b016

【便利ツールその3】go-spew

davecgh/go-spew

デバグとかで使えるpretty print系です。

spew.Dump(tweet)

をテストコードに追加すると

https://gyazo.com/e8b85380d43b957d0384874ea954ce2b

こんな感じです。

ソースコード

補完系だとgocodeがあります、、が、あまり良さがよくわかっていないので特に推しません。

atomユーザはautocomplete-goを入れることで使えます。

【interfaceとは】エラーの拡張

エラーの拡張を通して interface をなんとなく知ります。

まずerrorの定義です。

type error interface {
    Error() string
}

つまり、文字列を返すError()とう関数を持っていればいいわけです。

ここでは

  • どんなオペレーションを行っていた時のエラーなのか
  • どんなURLにアクセスしようとしたのか
  • どんなURLにリダイレクトされたのか

といった情報を持ち、文字列を返すError()とう関数を持っているErrorという構造体を定義します。

type Error struct {
    Op            string // the failing Operation (Request, Redirected, Parse)
    GetURL        string // the getting url
    RedirectedURL string // the definitive url
    Err           error  // the reason the get failed
}

func (e *Error) Error() string {
    return "please input error log"
}

ソースコード内では

doc, err = goquery.NewDocument(url)
if err != nil {
    err = &Error{
        Op:     "Request",
        GetURL: url,
        Err:    err,
    }
    return
}

if url != doc.Url.String() {
    err = &Error{
        Op:            "Redirected",
        GetURL:        url,
        RedirectedURL: doc.Url.String(),
    }
    return
}

のように拡張したエラーを返します。

パッケージを使用する側では

Convey("Given non-available tweet url\n", t, func() {
    url := "https://twitter.com/statuses/418033823511629836"
    _, err := simpletwitter.NewTweet(url)

    So(err, ShouldNotEqual, nil)
    So(err.(*simpletwitter.Error).Op, ShouldEqual, "Redirected")
})

のように型アサーションして使います。

また、そのまま、他パッケージの関数のerrをそのまま使いたいのであれば

func (e *Error) Error() string {
    return e.Err.Error()
}

とすればいいわけです。

このように、後でログ分析しやすいように Error()関数の出力を調整することができます。

なんとなくinterfaceがわかった気がしないでもないです。。。

ドキュメント

【便利ツールその4】godoc

godoc - GoDoc

go get golang.org/x/tools/cmd/godoc

で入ります。

godoc -http=:6060

して、http://localhost:6060 にアクセスしてみます。

https://gyazo.com/2aa8cf7057cae54050e4d9efbc93dc95

$GOPATH下にあるパッケージが見れます。

今回の場合は http://localhost:6060/pkg/github.com/sosuke-k/simpletwitter/ を見てます。

https://gyazo.com/19761d35c5e95d976608f4ec3b1d0c2e

まだ何も書いてないのにある程度中身がわかります。

package xxxの上や関数や構造体の宣言の上にコメントを書くことで godocで見た時に反映されるので、書いていきます。

例えば、simpletwitter.go を作り

simpletwitter.go
/*
Package simpletwitter uses goquery(https://github.com/PuerkitoBio/goquery) to fetch tweets.

Example:

  tweet err := simpletwitter.NewTweet(url)
  if err != nil {
    if err.(*simpletwitter.Error).Op = "Redirected" {
      ...
    }
  }
  fmt.Println(tweet.ScreenName + " : " + tweet.Text)

*/
package simpletwitter

とすると

https://gyazo.com/e09dbf43883f2f88e3b3e4d6bfb9c020

のようなOverviewドキュメントが作られます。

コメント内でインデントすることで、その行がコードシンタックスになるみたいです。

終わりに

長くなりました。

ドキュメントがしっかりしてないライブラリは使う気にならないですよね。

かと言って、作った側は十分使えるわけで、めんどくさいですよね。

オープンソース系にコミットしている人たちはほんとに素晴らしいと思います。

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
20