Go 勉強中
いまさらGo 勉強中。なかなか、いい。好みだ。言語仕様がリッチじゃないところが好き。コンパイラの質が上がれば、システム用言語として本当に使えるんじゃないだろうか。
感覚としてはCとPythonの間って感じ。Pythonと違って型があるので、コンパイル時のエラーチェックが期待できる。その割にほとんどの型宣言を省略できるので、書くのも楽だ。センスいいなあ。
ライブラリもかなりそろってる。 ここをみると、普通に必要そうなものはだいたいある感じ。AST(Abstract Syntax Tree) とかELFパーザとか、普通に必要なさそうなものまである(-_-)。パッケージの名前付けが、Javaっぽいので、どこに何があるかがなんとなくわかるのがうれしい。
エコーサーバー
ネットワークまわりはどんなものかと、エコーサーバを書いてみた。コードの意味は自明だと思う。変数の型宣言を一つもしてないところに注目。
package main import "net" import "io" func main() { addr := net.TCPAddr{net.ParseIP("0.0.0.0"), 3000} listner, _ := net.ListenTCP("tcp4", &addr) for { con, _ := listner.AcceptTCP() go io.Copy(con, con) } }
面白いのは、下から3行目の「go」。これがgoroutineというやつで、コンカレントに動くプログラムが簡単にかける。ここでは複数のクライアントを並行して捌くために使っている。こんなに簡単に書けるのは感動的だ。
もう一つ面白いのは
io.Copy(con, con)
con は net.TCPConn 型。一方 io.Copyは次のようにio.Writerとio.Reader を引数に取る関数である。
func Copy(dst Writer, src Reader) (written int64, err os.Error)
Writer型、Reader型は、それぞれ 「Read/ Writeという関数が定義されている型」として定義されている。
type Reader interface { Read(p []byte) (n int, err os.Error) } type Writer interface { Write(p []byte) (n int, err os.Error) }
net.TCPConnにはこの二つの関数が定義されているので、WriterでありReaderでもあるということになるわけだ。いわゆるダックタイピングなのだが、Python や Rubyのそれと違って、ちゃんと型がinterfaceとして定義されているので、型チェックが効く。
goにはobjectはなくstruct だけ。structなので複合リテラルとして初期化できる。この部分は括弧が「()」でなく「{}」 になってることからもわかるように、関数呼び出しではなく複合リテラルだ。
net.TCPAddr{net.ParseIP("0.0.0.0"), 3000}