Skip to content

Instantly share code, notes, and snippets.

@podhmo
Last active September 28, 2025 15:16
Show Gist options
  • Save podhmo/64d50c84ed50fe156a22404a0314321a to your computer and use it in GitHub Desktop.
Save podhmo/64d50c84ed50fe156a22404a0314321a to your computer and use it in GitHub Desktop.
gopkg -- goのツールチェインまわりは独特というか癖がありgopkgというコマンドを作ろうと考えてみていた

gopkg -- goのツールチェインまわりは独特というか癖がありgopkgというコマンドを作ろうと考えてみていた

特徴

gopkgはgoのモジュールの内外を含めたパッケージの情報を収集して表示するための便利なサブコマンドのセット。 (ほしいのは本当にCLIのコマンドなのか分かっていない)

サブコマンド

  • gopkg name ... -- package pathからパッケージ名を返す (go listのラッパー)
  • gopkg info -- 必要な情報を返す (pkg.go.dev?)
  • gopkg version ... -- 提供されているバージョンを一覧で返す (goproxyにアクセス?)
  • gopkg dep -- パッケージの依存を把握する
  • gopkg list -- 関連するパッケージの情報が一覧で返ってくる (go listのラッパー?)

実験的なもの

  • (gopkg search -- これはどうやって管理すれば良いんだ?)
  • (gopkg def . -- goto definitioni的なもの (code -g :とかの形式でアクセスできるとか))
  • (gopkg imports -- golistのラッパーにするべき?)
  • (gopkg tests , runに渡す用のラッパーを作りたい?,fuzzy find?)
  • (gopkg inspect -- goinspectのような呼び出し関係を把握したい(名前は要検討))

検討事項

  • いつでもどこでも相対パスでの指定ができる (./foo, ./foo/...)
  • ファイルもパッケージパスも渡せる
    • gopkg version <binary>go version -m <binary> などとして扱われる
    • gopkg def ./xxx/yyy.go:Foo は ./xxx:Foo としても扱える
  • go.modの依存外のパッケージの情報も得ることができる

詳細

ここはサブコマンドの詳細

gopkg name

パッケージ名を得る。

go.modに無い場合は以下のようなかんじで一時ディレクトリにgo.modを作って無理矢理でも実行する。

$ go mod init m
$ go get github.com/go-chi/chi/v5
$ go list -f "{{.Name}}" github.com/go-chi/chi/v5
chi
$ go list -f "{{.Name}}" github.com/go-chi/chi/v5/middleware
middleware

(実験的な機能としてpackage名だけでpackageパスを探せると嬉しい?別コマンドにするべき? 'gopkg path chi) (gopkg infoをjqで絞りこむだけで良い説もある)

gopkg info

情報を返す

--web でpkg.go.devが開けるとうれしい気がする。あとはLLM用の出力も返せるとうれしい? デフォルトはJSONで良い気がする。go.modの管理下の場合かつ依存を持っていた場合にはgo.sumで利用しているバージョンを返すことにする?

# $ gopkg info chi
$ gopkg info github.com/go-chi/chi/v5
{
  "name": "chi",
  "path": "github.com/go-chi/chi/v5",
  "doc:" "https://pkg.go.dev/github.com/go-chi/chi/v5",
  "versioni?": "v5.2.1",
  "latest": ""
}

パッケージ名でもいけるようにするか?gopkg info $(gopkg path chi) とかで書くのはめんどうなきがする。 あとはバージョンも指定できるほうが嬉しい気がする。go pkg info -web chi@latestバージョン指定がない場合はgo.modの依存にある場合とない場合とで分ける?

(gopkg list で現在のgo.mod内の外部依存の一覧がでるべき? gopkg list ./... は内部依存の一覧。こういう感じで複数のコンテキストを混ぜあわせた挙動をしてほしいということかもしれない) (gopkg info <package path>:<symbol> でgopkg defを兼ねても良いきがしてきた。直接その関数のドキュメントに飛びたいきがする。これはgopkg docにするべき?)

gopkg version

これは一覧を返すべき?go.mod内なら使われているバージョンを返すべき?たとえばGOPROXYのprotocolを使って以下のような結果を返すことはできる。

なんとなくgopkg version <package> ならバージョンが一覧で返ってきて、gopkg version <package>@latestなどバージョンの場合には内部的な情報が返ってくると良いきもする?

$ curl https://proxy.golang.org/github.com/go-chi/chi/v5/@v/list
v5.0.11
v5.0.10
v5.1.0
v5.2.3
v5.0.7
v5.2.0
v5.0.9
v5.0.2
v5.2.2
v5.0.5
v5.0.14
v5.0.0
v5.0.6
v5.0.8
v5.0.4
v5.0.12
v5.0.13
v5.2.1
v5.0.3
v5.0.1

このときのlatest versionはv5.2.3であってるのかな?

latestの情報がほしい場合は go mod download -json <package>@latest でも良いきがする。これは毎回ダウンロードしてしまうもの? go list -m -json <package>のほうがモジュール内なら親切?

$ go mod download -json -x github.com/go-chi/chi/v5@latest
{
	"Path": "github.com/go-chi/chi/v5",
	"Version": "v5.2.3",
	"Query": "latest",
	"Info": "/home/po/go/pkg/mod/cache/download/github.com/go-chi/chi/v5/@v/v5.2.3.info",
	"GoMod": "/home/po/go/pkg/mod/cache/download/github.com/go-chi/chi/v5/@v/v5.2.3.mod",
	"Zip": "/home/po/go/pkg/mod/cache/download/github.com/go-chi/chi/v5/@v/v5.2.3.zip",
	"Dir": "/home/po/go/pkg/mod/github.com/go-chi/chi/[email protected]",
	"Sum": "h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE=",
	"GoModSum": "h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops="
}

ファイルというかバイナリを渡したときはgo versionとして機能してくれれば良い。

$ gopkg version $(which ghq)  # go version $(which ghq)
/home/po/go/bin/ghq: go1.22.2

$ go version -m $(which ghq)
/home/po/go/bin/ghq: go1.22.2
	path	github.com/x-motemen/ghq
	mod	github.com/x-motemen/ghq	v1.6.1	h1:SHmjNYgN66Nl/j9+OGYUhZEEpoqC5RpQBl5JkrC5MXI=
	dep	github.com/Songmu/gitconfig	v0.2.0	h1:pX2++u4KUq+K2k/ZCzGXLtkD3ceCqIdi0tDyb+IbSyo=
	dep	github.com/cli/go-gh	v1.2.1	h1:xFrjejSsgPiwXFP6VYynKWwxLQcNJy3Twbu82ZDlR/o=
	dep	github.com/cli/safeexec	v1.0.1	h1:e/C79PbXF4yYTN/wauC4tviMxEV13BwljGj0N9j+N00=
	dep	github.com/cpuguy83/go-md2man/v2	v2.0.4	h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
	dep	github.com/daviddengcn/go-colortext	v1.0.0	h1:ANqDyC0ys6qCSvuEK7l3g5RaehL/Xck9EX8ATG8oKsE=
	dep	github.com/fatih/color	v1.16.0	h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
	dep	github.com/goccy/go-yaml	v1.11.3	h1:B3W9IdWbvrUu2OYQGwvU1nZtvMQJPBKgBUuweJjLj6I=
	dep	github.com/mattn/go-colorable	v0.1.13	h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
	dep	github.com/mattn/go-isatty	v0.0.20	h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
	dep	github.com/motemen/go-colorine	v0.0.0-20180816141035-45d19169413a	h1:CONqI/36EjYzkAzrMD0UWuL/lRDr7UdoID4fDGke+Yc=
	dep	github.com/russross/blackfriday/v2	v2.1.0	h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
	dep	github.com/saracen/walker	v0.1.4	h1:/WCOt98GRkQ0KgL6hXJFBpoH21XY6iCD2N6LQWBFiaU=
	dep	github.com/urfave/cli/v2	v2.27.1	h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho=
	dep	github.com/xrash/smetrics	v0.0.0-20240312152122-5f08fbb34913	h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw=
	dep	golang.org/x/net	v0.23.0	h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
	dep	golang.org/x/sync	v0.6.0	h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
	dep	golang.org/x/sys	v0.18.0	h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
	dep	golang.org/x/xerrors	v0.0.0-20231012003039-104605ab7028	h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
	dep	gopkg.in/yaml.v3	v3.0.1	h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
	build	-buildmode=exe
	build	-compiler=gc
	build	CGO_ENABLED=1
	build	CGO_CFLAGS=
	build	CGO_CPPFLAGS=
	build	CGO_CXXFLAGS=
	build	CGO_LDFLAGS=
	build	GOARCH=amd64
	build	GOOS=linux
	build	GOAMD64=v1

gopkg dep

go mod graph を加工することでgo.mod自体の依存関係は把握できるかもしれない。しかしモジュール外の情報がとれない。 あとnpmの例は言うに及ばず依存関係を全列挙しても嬉しさはあまりない。

  • モジュール内つまりgo.modとgo.sumが存在するなら全ての依存をローカルで解決可能
  • モジュール外は結構たいへん
    • https://proxy.golang.org/<package>/@v/<version>.modにアクセスするとgo.modが取得可能だけれどバージョン指定が必要
    • go mod download -json <package>@latest の結果を集める?
  • いっそのことTUIの形式で開きtabか何かで開けるようにすると見やすい?

(モジュール内ではパッケージ単位での依存が気になるがそれは gopkg imports <> とかにわけるべき?)

gopkg list

これは gopkg list ./... とかをパッケージの一覧として展開させたい。

わかっていないこと

go list

  • go list -m -u は何を意味するのだっけ?、 go get -uと同様?
  • go list -m -jsongo list -json の使いわけをたびたびはまる。前者はモジュール単位の情報。後者はパッケージ単位。
  • モジュール外の情報はやっぱり取得できない。

go get

  • go get <package>@latest のlatestってどこかで取得できる?
  • go get <package>@none で削除という理解はかなり難しいきがする
  • go get -u <package> で最新に更新する
  • go get -t <package> でtoolディレクティブに含めるようになるのか?

go version

  • go get -m <binary> では結構色々な情報が取れる
  • go get -v <binary> の意味がわかっていない

go mod why

  • go mod whyは直接的な参照を渡すと (main module does not need package <package>) と言ってきて謎。
  • go.mod内の関節的な参照(indirect)の理由を調べるのに使う。-mはモジュールとして扱う。
    • たとえばtoolディレクティブにstaticcheckを入れた結果BurntSushi/tomlが入ったときに go mod why -m github.com/BurntSushi/tomlとかやる。

gopkg depの作成について

パッケージ単位の依存の話とモジュール単位の依存の話がある。

endpoints

  • pkg.go.dev はドキュメント
  • proxy.golang.org はgoproxy
  • sum.golang.org の使いみちは?

ツールスタック

これは単にLLMなどに渡すときに書いておく程度の内容

  • go1.24+
  • ログにはlog/slogだけを使ってください
  • デバッグプリントはslogのDebugを使ってください
  • テストコードのassertにはgo-cmpを使ってください
  • テストコードのassertでは変数名としてwant,gotのペアを使ってください
  • github.com/stretchr/testify は使わないでください
  • github actionsのciを追加してください(pull_request で types: [ opened, synchronize, reopened ])
@podhmo
Copy link
Author

podhmo commented Sep 28, 2025

後に気づくけどモジュールとパッケージを区別して考えたほうがよくバージョンが紐づくのはモジュール

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment