電卓片手に

io.Writer の入力を行ごとに処理する go ライブラリ

投稿日:

習作で golang を使って欲しいものを作っていたんだけど「dokku でいいか。」となってしまったので、 汎用的に使えそうな小さなモジュールだけ切り出して公開した。

用例としては、外部コマンドの標準出力入力を行ごとに処理をする、などがあります (cmdlogging.go):

package main

import (
	"github.com/kui/liner"
	"log"
	"os/exec"
)

func main() {
	// use the default line processor which just print lines with log.Printf
	outw := liner.NewLiningWriter(nil, nil)
	defer outw.Close()

	// use a custom line processor which just print lines with log.Printf
	errw := liner.NewLiningWriter(func(line string) error {
		log.Printf("stderr: %s\n", line)
		return nil
	}, nil)
	defer errw.Close()

	c := exec.Command("bash", "-c", "seq 5; seq 6 10 >&2")
	c.Stdout = outw
	c.Stderr = errw

	err := c.Run()
	if err != nil {
		log.Fatal(err)
	}
}

実行すると:

$ go run _example/cmdlogging.go
2016/01/31 16:23:23 1
2016/01/31 16:23:23 2
2016/01/31 16:23:23 3
2016/01/31 16:23:23 4
2016/01/31 16:23:23 5
2016/01/31 16:23:23 stderr: 6
2016/01/31 16:23:23 stderr: 7
2016/01/31 16:23:23 stderr: 8
2016/01/31 16:23:23 stderr: 9
2016/01/31 16:23:23 stderr: 10

golang の雑感

比較的新しい言語として既に触っている Rust と比べてしまうところはあるけれど、 目指すところが違うので用途によって分けるのが良さそう。

言語仕様がシンプル

どう書くか迷うことがあんまりない。Java も 7 まではそんな感じだった気がするけれど、 Lambda 式が入ってきてしまって書き方に迷うことが増えてしまった。

例外がないのは安心感ある

Rust もそうだけれど、例外がないのでエラーが起きる可能性があるステートが一目瞭然。

Java もどの例外を非検査例外にするのかが、ライブラリによってマチマチなのつらい。

例外っぽいものとして Panic はあるけど、基本的に起きたらプロセス死ぬし、 良くてHTTPリクエストを中断するかという極限られた用途だし。

結局スレッドセーフを意識しないといけないのか・・・

JavaScript 書いていて楽だなーと思っていたことが go routine で同様のことができるのかと 勝手に期待してしまっていたが、軽量スレッドみたいなものだった。

基本的に状態を共有せず、channel を使ったメッセージパッシングを使うことが前提になってはいて、 スレッドセーフを考える機会は減っているんだろうけれど。

開発ツール便利

そこそこコミュニティが大きくなっている影響か、もともとバンドルされているツールも良い感じの影響か、 Emacs で開発するのにとても便利なツールが安定して使えた。

使う人間の多さは大事。

null(nil) とまた戦うのか・・・

null のない世界に行きたい。

null がない言語って Rust しか触ったことないけれど、null をなくそうとするとまたシンプルな言語仕様では無くなってしまうのかな。

せめて Ceylon, Kotlin のように null を許容するか否かの型表現が欲しかった。

(Scala は Some(null) って書く人間がいてウンザリしたので、Scala は null がある世界だと思ってる。)

ジェネリクスはあってもなくてもいいかな

ジェネリクスは少し難しい。型に対して厳密になれるのはテストが減るなど嬉しいこともあるけれど、 文法が複雑になる。個人的にはこっちの方向性のほうが好きなんだけれど、難しいと使う人間が少なくなって、 開発ツールやライブラリのバリエーションが少なくなるのも困るので。

上述した null (nil) の扱いとかもこの辺が絡んできそうな感じではある。

あと、ジェネリクスが導入されてコンパイル速度が遅くなるのなら要らないと思う。

エラー処理辛い

これ沢山書いた:

if err != nil {
	return
}