Golang の terminal パッケージで file descriptor を引数として渡すときは int にキャストしよう
先日、こんなコードを見つけたのでキャストいらないのではって PR を送ったら、キャストしないとWindows でダメだったって言われたので調べてみました。
terminal.ReadPassword(int(syscall.Stdin))
Issue
cannot use syscall.Stdin (type syscall.Handle) as type int in argument to terminal.IsTerminal
こういう怒られ方をするらしいです。
GoDoc を見てみる
var ( Stdin = 0 Stdout = 1 Stderr = 2 )
なるほど int。ってなるけどこれは Linux 用のドキュメントらしいです。
https://go-review.googlesource.com/c/tools/1371
この変更で GoDoc にパラメータで GOOS
と GOARCH
を渡せるようになったらしいのでみてみます。
https://golang.org/pkg/syscall/?GOOS=windows#pkg-variables
var (
Stdin = getStdHandle(STD_INPUT_HANDLE)
Stdout = getStdHandle(STD_OUTPUT_HANDLE)
Stderr = getStdHandle(STD_ERROR_HANDLE)
)
getStdHandle
の定義はこうなっています。
func getStdHandle(h int) (fd Handle) { r, _ := GetStdHandle(h) CloseOnExec(r) return r }
func GetStdHandle(stdhandle int) (handle Handle, err error)
完全に理解した。
なのでキャストしないと
cannot use syscall.Stdin (type syscall.Handle) as type int in argument to terminal.IsTerminal
って怒られ方をするんですね。
おまけ
unconvert という不要なキャストを検知してくれる Linter があるんですが、オプションで -all
を渡すと GOOS/GOARCH
の組み合わせまで見てくれて、全ての場合で不要の時のみ怒ってくれるらしい。かしこい。