2020/02/23

[golang]mutexもある

いかんいかん、golang気を抜くと学習を忘れてしまう。
そして、気を抜くとgolang自体忘れかねない。。。

 

goroutineをちょっとだけやったが、そのときはデータの受け渡しにchanを使った。
しかし、スライスを渡せる以上、メモリの共有もできるということだ。
ならばセマフォなりmutexなりの機構があるはずだ。


mutexは、ある。

Go でロックする - Qiita
https://qiita.com/mrasu/items/7531a5a28e9fda77aa5e#%E7%B5%82%E3%82%8F%E3%82%8A%E3%81%AB

 

まあ、mutexはありがちだからよいとして、WaitGroupというものがあるそうだ。

WaitGroupは「Addした回数Doneされるまで待ち続ける」という命令を書けるようにした仕組みです。

セマフォっぽい使い方になるのかな?

waitgroup.goにはAdd() / Done() / Wait()があって、関連するオブジェクトをAddするとかいうものではなく、単にカウントだけの管理をしているようだ。
ちなみにDone()は、Add(-1)になってる。

 

かといって自分で好きな負の値を書いていくのは良くない気がする。
race.ReleaseMerge()は1回だけだし。
いや、そもそもrace.Enableとかやってるけど、raceってWaitGroupオブジェクトごとに持ってるんじゃなくて、importしてるからグローバルな値よね?

・・・race.Enableはconst値じゃった。

 

まだgolangのソースコードに慣れていないのだが、データの持ち方としては、こんな感じだろうか。

  • 外側にある大文字の変数名は、公開されたグローバル変数
  • 外側にある小文字の変数名は、公開されてないグローバル変数(Cでいうところのstatic変数)
  • 関数名の前に括弧して変数定義がある場合は、クラス変数っぽいやつ
  • 関数の引数
  • 関数内で宣言したスタックとかmakeした変数

 

goroutineで共有するなら、グローバル変数やmakeした変数がよかろう。
関数の引数は、元がどうやって宣言されているかによるから、なんともいえんな。


というわけで、簡単にグローバル変数を試すことにした。
mutexの話をしているはずなのに、グローバル変数を試すことになるとは。。

 

src/cmd_ex5/main.go

01: package main
02: 
03: import "ex5"
04: 
05: var MainVal int
06: 
07: func main() {
08: 	MainVal = 20
09: 	ex5.Ex5Val = 30
10: 	ex5.FuncEx5b()
11: 	MainVal = 10
12: 	ex5.Ex5Val = 55
13: 	ex5.FuncEx5b()
14: }
  

 

src/ex5/ex5b.go

01: package ex5
02: 
03: import (
04: 	"fmt"
05: )
06: 
07: var Ex5Val int
08: 
09: func FuncEx5b() {
10: 	fmt.Printf("FuncEx5b: %d\n", Ex5Val)
11: 	//fmt.Printf("MainVal: %d\n", main.MainVal) //compile error
12: }
  

 

$ go run cmd_ex5
FuncEx5b: 30
FuncEx5b: 55

 

main関数は、mainパッケージに置く。
mainパッケージに置いたグローバル変数は、mainパッケージの担当だろう。
しかし、ex5パッケージからはmain.MainValにアクセスできなかった。
逆はできるので、言語仕様だろうか。

まあ、パッケージにpublicなグローバル変数を用意するよりは、getter/setterなんかでアクセスさせた方が安全な気はするが、言語的にできないのとは違う。

ディレクトリ名をmainにしなかったせいか?
しかし、実行ファイルをいくつか作りたい場合はcmd以下にディレクトリを作ろう、というのが推奨だったと思う。
cmd/ex5/mainなんかにしてみたが、ダメだ。
main関数があるとダメなのかと思ったが、そうでもない。

 

うーん、わからん。。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。