この前GoのWebアプリケーションフレームワークのgojiのソースコードを見ていてなるほど!と思ったので紹介します。
GoでtcpやUNIXドメインソケットやファイルディスクリプタをbindしたサーバーを立てたくなることはよくあります。そういう時は標準ライブラリのnet/http
のnet.Lister
を作るところだけ分岐すれば後は共通的に扱えます。
なので適当にflag
で指定して、tcpなら-tcp
で、UNIXドメインソケットなら-sock
でみたいな感じで指定するのが普通だと思いますが、gojiはちょっと違います。
gojiではtcpでもUNIXドメインソケットでも-bind
でbind先を指定します。そのときの判定処理が以下のようになっています。
goji/bind.go at master · zenazn/goji
func listenTo(bind string) (net.Listener, error) {
if strings.Contains(bind, ":") {
return net.Listen("tcp", bind)
} else if strings.HasPrefix(bind, ".") || strings.HasPrefix(bind, "/") {
return net.Listen("unix", bind)
} else if strings.HasPrefix(bind, "fd@") {
fd, err := strconv.Atoi(bind[3:])
if err != nil {
return nil, fmt.Errorf("error while parsing fd %v: %v",
bind, err)
}
f := os.NewFile(uintptr(fd), bind)
defer f.Close()
return net.FileListener(f)
} else if strings.HasPrefix(bind, "einhorn@") {
fd, err := strconv.Atoi(bind[8:])
if err != nil {
return nil, fmt.Errorf(
"error while parsing einhorn %v: %v", bind, err)
}
return einhornBind(fd)
}
return nil, fmt.Errorf("error while parsing bind arg %v", bind)
}
-
:
が含まれていたらtcp-
:8080
とか127.0.0.1:8080
とか
-
- 先頭が
.
か/
ならUNIXドメインソケット-
./tmp/server.sock
とか/tmp/server.sock
とか
-
-
fd@
から始まっていたらファイルディスクリプタで4文字目にファイルディスクリプタを続ける-
fd@8
みたいな指定でファイルディスクリプタを使える
-
-
einhorn@
から始まっていたらEinhorn- こういうのもあるらしい
他にもやられている手法なのか知らないのですが、うまい指定方法だなーと思ったので参考になれば