🦊

Goでライブラリを作った話

2022/07/24に公開

どうも、こまもかです。
今回は前回紹介したGo製Twitterライブラリを作った際に得た知見をまとめていきます。

go mod で苦しんだ

一番悩んだところです。何ならこれを書く為の記事のようなものです。

go mod init、何を書くねん

プロジェクトを作成する時にgo mod initを実行しますが、まずここに何を書けば良いか分からない。
調べた所、Githubで公開する場合はgithub.com/{User Name}/{Repo Name}の様に指定するのが良さそうです。

ローカルで読み込めへん...

次に作ったライブラリを配下のディレクトリに読み込ませる方法についてです。これは中々良い感じの情報が出て来なかったので苦戦しました。
結論としては、go.modreplace "読み込みたい名前" => 実際の相対パスの様に指定します。

想定するディレクトリ構造

.
├── README.md
├── exsamples
│   ├── GetProfile
│   │   ├── go.mod
│   │   ├── go.sum
│   │   └── main.go <- ここで読み込む
│   └── SearchTweets
│       ├── go.mod
│       ├── go.sum
│       └── main.go <- ここで読み込む
├── go.mod
├── go.sum
├── thin.go <- 本体
└── thin_test.go
module github.com/Comamoca/thin

go 1.18

// replaceで置換が可能になる
replace "github.com/Comamoca/thin => ./exsample/GetTweets/"

require (
	...
)

名前空間が衝突した

ライブラリ側で提供する関数の一つにGet()という物がありました。これはそもそも命名の時点でかなり怪しいのですが、実装した時はまだ正常に動いていたのでそのままにしていました。
しかし、テストコードを書いて実行してみたらエラーになり、そこでその関数が想定と違う挙動をしている事に気付きました。

原因はthinのClientがhttpのClientと衝突していて、client.Get()https.Get()を実行しているように解釈されてしまった事です。
そこで、thin.Clientのclient属性を*http.Clientとする事でエラーを回避しました。Goには継承の概念がないので、多分これが現状で一番良い方法だと思っています...

レシーバは良いぞ

前に述べたように、ライブラリが提供する関数と標準ライブラリが提供する関数がバッティングしてしまったので、要素を構造体でラップしました。
そしてこの様に呼び出せるようになりました。

client := keys.Auth()
thin.Get("URL")

挙動には満足していたので、このままでも良かったのですが、せっかくなのでレシーバにしてみました。すると、.をを使って呼び出せると補完がいい感じに効いてくれてかなり書き心地が良くなりました。
また、メソッドチェーンが書けるという思わぬメリットも出てきました。

// 一行で済ませられる
resp := keys.Auth().Get("URL")

まとめ

今回はGoでライブラリを作るときに引っかかった事について書きました。Goは書きやすくて気に入ってるのでこれからも色々書いていきたいです。

GitHubで編集を提案

Discussion