Go に暗黙の型変換はない
Go には Tour of Go でも習うように,暗黙の型変換といったものは存在せず,明示的に型変換をする必要があります.
Unlike in C, in Go assignment between items of different type requires an explicit conversion. – Type conversions https://tour.golang.org/basics/13
このデザインについては FAQ にも書いてあります. FAQ: Why does Go not provide implicit numeric conversions? https://golang.org/doc/faq#conversions
(厳密には interface への変換だけは勝手にやってくれるのでその意味では暗黙の型変換はあるといえる気もします)
このデザインは僕も好きです.The Zen of Python も言うように何事も “Explicit is better than Implicit” だと感じます. Go ではほぼ全ての機能が Explicit に表現され,Go の Readablity に繋がっています. はぁ…Go かわいいよ Go…
しかし,そうは言ってもint->int64などの安全な変換ふくめてひたすら手で型変換しなきゃいけないのはつらいこともあります.
競技プログラミングといった書捨てスクリプトで最初は int でやってたけど,int64 に変換しなきゃ…というときや,
func max(x int64, ys ...int64) int64
っていうテンプレ関数を用意していても,型が int
のままでは使えず毎回 int64()
で囲ったり int()
で戻したりする必要があります.
これは人間のやる仕事じゃない…ということでこの問題を解消するツール, go-typeconv を作りました.
go-typeconv 作った
haya14busa/go-typeconv: Bring implicit type conversion into Go in a explicit way
gotypeconv は Go のソースコードを受け取って,型まわりのエラーを見つけ,AST を自動で書き換えて修正します. gofmt と同様に,stdout に修正後のコードをプリントしたり,ファイルを直接書き換えたり,diffを表示することが出来ます.
最終的には明示的な型変換を使ったソースコードになるけど,その変換をある意味暗黙的にやってくれる.というのがコンセプトです.
インストール
1
|
|
使い方
./testdata/tour.input.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
上記のコードは以下で示すように型変換周りでエラーがでます.
1 2 3 |
|
gotypeconv を実行するとこの通り!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
func max(x int64, ys ...int64) int64
といったテンプレートあるけど int
では使えない…というときもこの通り.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
vim-gofmt
haya14busa/vim-gofmt: Formats Go source code asynchronously with multiple Go formatters.
Vim で実行したい場合は (Experimentalですが) vim-gofmt というGoの formatter を複数,非同期で実行するプラグインを作成したのでこれを使ってみてください.
設定例:
1 2 3 4 5 |
|
実行: (filetype が Go のカレントバッファで) :Fmt
正直ワンバイナリでやってほしいけど,gofmt -s
と goimports
が同時に実行できないので,
いずれ複数フォーマッタ対応のVim プラグイン 欲しいなと思ってたので作りました.
どちらも,特に gofmt はかなり高速なので複数実行してもあまり気になりません.
なお非同期にgofmt実行するといっても,バッファが書き換えられていたら上書きしたりするような挙動ではないので安心してください. (不具合あったら直します)
なお
1
|
|
とか書いておくと:GoTypeConv
でgotypeconv だけ実行出来たりしますが,API は変わるかも知れないのでご注意ください.
また以下のようにすると保存時に自動で実行できます.が,APIは(ry
1 2 3 4 |
|
機械で出来ることは機械にやらせたい
年代別で見るコンパイラちゃんの進化 #擬竜化 pic.twitter.com/7zmiskfjmE
— RAO(らお) (@RIORAO) February 3, 2017
途中で IDE ちゃんになっているようですが,Go の場合 IDE ちゃんじゃなくても大丈夫!
りんなにC#教えてもらおうとしたら物凄い返信きた pic.twitter.com/9jz5dtfPJd
— ダーシノ (@bc_rikko) February 5, 2017
The grammar is compact and regular, allowing for easy analysis by automatic tools such as integrated development environments. – The Go Programming Language Specification - The Go Programming Language
Go は spec にまで書かれているように,Goのためのツールを書くのはとても簡単です.
修正系ツールだけでも
gofmt -s
はフォーマットだけでなくシンプルにかけるところを自動で修正してくれgoimports
は自動で import 文を追加したり削除したりしてくれgotypeconv
は型変換エラーを自動で修正してくれます
また proposal: gofmt: Add option to ignore parse error if no bad node in AST · Issue #18939 · golang/go のプロポーザルにあるように,実は末尾コンマがないといったエラーも自動で修正できます. (gofmtに入るかはわからないけど個人的には入って欲しいなー)
なお https://github.com/rhysd/gofmtrlx を入れると末尾カンマは修正してくれますし,実は go-typeconv も勝手に修正してくれます.
gosimple という simple にかけるところを教えてくれる linter もあります. (自動修正機能は今の所ないけどオプションあっても良い気がするなー)
linter がたくさんあることは Go の CI で lint と カバレッジ回して非人間的なレビューは自動化しよう in 2016年 - haya14busa で紹介しました.
go/* を使えばパッケージをソースコードをパースして AST を取得したり, それを Format された形式で print したり,型情報を取得したり… などと言ったことが簡単にできます.
golang.org/x/tools/go/loader を使えば,簡単に型情報を使える形でプログラムをロードできますし, golang.org/x/tools/go/ssa なんてものもあります.
go/*
パッケージ だけでなく,golang.org/x/tools/go 下のパッケージをみても面白いです.
AST ベースのツールは他言語でもたくさんあると思うので比較的わかりやすいですが, 型情報まで使えるパッケージを提供している言語はそんなになくて難しいですが,godoc の他にも公式チュートリアルが参考になります.https://golang.org/s/types-tutorial
日本語情報でも motemen さんの GoのためのGo や tenntenn さんの各種記事 goパッケージで簡単に静的解析して世界を広げよう #golang - Qiita が詳しいです.
ぜひ,みなさんもGoのためのGo ツール作ってみると面白いかと思います. いろんなことができるので,なかなか楽しいです.
はぁ…Go かわいいよ Go…(ため息)