Try Golang! GoでJavaライクにStringを扱おうとしたら、、

What you should be careful about Go “string” if you are a Java programmer.

すごい初歩的なはなし。JavaのStringとGoのstringには根本的な違いがあります。JavaのStringはnullとなり得ますが、Goのstringにはnullが入りません。ポインタに関する思想の違いですね。

Goの場合は「ポインタについては自分で扱え」という基本思想があるため、nullと空文字とをはっきり分けて考える必要がある場合は、ポインタ型として*stringと宣言してあげる必要があります。

では、JSONのパースを例に、挙動を見てみましょう。

stringで宣言した場合

テスト用のソースコードはこちら。

実行結果は以下のようになります。

$ go run main.go
Foo
<empty>
<empty>
<empty>

nullを設定したfield3も、未設定のfield4も、空文字として扱われていますね。うーん、これはいまいち。

*stringで宣言した場合

上のサンプルコードについて、二箇所修正します。

  1. 構造体DataのField定義をstringから*stringに変更
  2. convEmptyメソッド呼出し時、引数の&を削除

1の対応が、「ポインタ型で定義する」対応です。2はコンパイルを通すためだけ。これを実行してみると、結果は以下のように変わります。

$ go run main.go
Foo
<empty>
<nil>
<nil>

field3field4が、期待通りnilと判定されましたね。


JavaやPHPなど、ポインタが完全に隠蔽されている言語が多いので、Goで初めてポインタが出てくると戸惑うこともあるかもしれません。言語の思想の違いを正しく理解して、上手く付き合いたいものですね。