2021/12/19

[golang]ライブラリが持つグローバル変数

グローバル変数と呼んでよいのかどうかわからんが、パッケージ内に変数を置けばグローバル変数みたいな扱いができると思う。
小文字だとパッケージ外からはアクセスできないが、ローカル変数かグローバル変数かでいえばグローバル変数だからどこからアクセスしても本体は同じだ。

 

さて、ではこれがライブラリだったらどういう扱いになるのだろうか?
もし1箇所でしか使っていないなら気にしなくてよいと思うが、複数のパッケージで同じライブラリを import していたら、それは別のメモリとして扱われるのか、同じメモリとして扱われるのか。

https://github.com/hirokuma/gogo-test3

https://github.com/hirokuma/gogo-test4

gogo-test3 の中にパッケージ gogo1 と gogo2 があって、それぞれグローバル変数(パッケージ変数、の方が良いのか?)を置いている。
そしてそれぞれが gogo-test4 を import している。

gogo-test4 はグローバル変数がある。

gogo-test3 の main() で、gogo1 の中で gogo1 と gogo-test4 を更新 → gogo2 の中で gogo2 と gogo-test4 を更新 → gogo1 側の gogo-test4 の値を見てみる、ということをやっている。
結果はこうなる。 2つ数値が出力されるうち、前者が package 内のグローバル変数、後者が gogo-test4 のグローバル変数である。

$ go run .
gogo1 10, 10
gogo2 20, 20
gogo1 10, 20

gogo2 で設定した gogo-test4 の値が gogo1 の方でも取得されているので、取りあえずこういうシンプルな書き方であれば import を複数の箇所で行っていても 1つのものだと判定されるようだ。
New 関数を package が持っていることが多いのは、動的に変数を用意しないと知らないところからアクセスされて値が書き換わっていた、なんてことが起きてしまうのを防ぐためだ。
あるいは、どこからアクセスしても同じデータを使いたいなら、あえてそう作ればよいということだ。