TCPListenerのファイルディスクリプタを調べる

ListenしているSocketのfdを知りたいが、net.Listenerのインターフェースをみても取得する方法がないのでググったら、

http://naoina.plog.la/2013/11/12/235753683181

こんな記事をみつけた。

Socketからfdが取得できないのは、POSIX縛りになるからだと思われるが、ここで方法へどうやって辿りついたかよくわからなかったので調べてみた。

TCPListenerの定義を調べると、

// src/pkg/net/tcpsock_posix.go
type TCPListener struct {
  fd *netFD
}

となっているので、reflectパッケージを使えば、

 reflect.Indirect(reflect.Indirect(reflect.ValueOf(listener)).FieldByName("fd"))

で、fdの構造体が取得できる。

また、netFDの定義は、

// src/pkg/net/fd_unix.go
// Network file descriptor.
type netFD struct {
    // locking/lifetime of sysfd + serialize access to Read and Write methods
    fdmu fdMutex

    // immutable until Close
    sysfd       int
    family      int
    sotype      int
    isConnected bool
    net         string
    laddr       Addr
    raddr       Addr

    // wait server
    pd pollDesc
}

となっているから、

 uintptr(fdValue.FieldByName("sysfd").Int())

で、ファイルディスクリプタの値が取得できる、ということのようだ。