20210610のGoに関する記事は2件です。

how to stop groutine with channel

overview バックグラウンド等で動かすgoroutineを使ったforループプログラムで、シグナルを受け取った際に終了させる処理例 example1 ここではシグナルの代わりに適当なチャンネルを使う。 package main import ( "fmt" "time" ) func main() { c := make(chan string, 1) sig := make(chan string, 1) go func(){ for{ fmt.Println("Hello") select{ case s := <-c: fmt.Println(s) sig<-"FINISH" return default: } time.Sleep(1 * time.Second) // } }() time.Sleep(10 * time.Second) c<-"done" s:= <-sig fmt.Println(s) } example2 実際にシグナルを使った例 package main import ( "fmt" "os" "os/signal" "syscall" "time" ) func Loop(c chan os.Signal, done chan int) { go func() { for { fmt.Println("do something....") select { case s := <-c: fmt.Println("Got signal:", s) close(c) done <- 0 return default: } time.Sleep(1 * time.Second) } }() } func main() { sig := make(chan os.Signal, 1) signal.Notify(sig, syscall.SIGTERM, syscall.SIGINT) done := make(chan int) defer close(done) Loop(sig, done) <-done fmt.Println("Exit") os.Exit(0) } 実行結果 mainではdoneチャンネル受信待ちにする。 シグナルを送るとチャンネルに送信される。 所定の処理が終わったあとにチャネルを受信する。シグナルが来ていなければ処理を継続。シグナルが来ている場合はdoneチャンネルに送信する、mainでdoneチャンネルを受信し処理を終了する。 $ go run signal.go do something.... do something.... do something.... do something.... do something.... do something.... do something.... do something.... do something.... do something.... do something.... ^Cdo something.... Got signal: interrupt Exit
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

goでスレッド処理する。

はじめに Go言語でスレッド処理について やったメモを記載します。 実践 単純なスレッド 以下のmain関数内のthread()の処理部分をスレッドさせます。 main.go package main import ( "fmt" "time" ) func thread() { time.Sleep(time.Microsecond * 100) fmt.Println("test") } func main() { thread() } 例えば以下のようにgoとつけることで、スレッドできますが、処理が終わる前にメイン処理が終わってしまうため 実行しても何にも表示されません。 main.go package main import ( "fmt" "time" ) func thread() { time.Sleep(time.Microsecond * 100) fmt.Println("test") } func main() { go thread() } 実際に、channelsの機能を使用して、スレッドの処理がおわるまで処理させる場合は以下のように変更します。 main.go package main import ( "fmt" "time" ) func thread() { time.Sleep(time.Microsecond * 100) fmt.Println("test") } func main() { ch1 := make(chan bool) go func() { thread() ch1 <- true }() <-ch1 } 複雑な処理 以下のように、0~100までの数をnとしたときに、0~nまでの数を和を求めるものとします。 main.go package main import "fmt" func thread(num int) int { output := 0 for i := 0; i < num; i++ { output += i } time.Sleep(time.Microsecond * 10) return output } func main() { output := []int{} for i := 0; i < 100; i++ { tmp := thread(i) output = append(output, tmp) } fmt.Println(output) } もし、同じ結果を得るような内容のスレッド化する場合は、以下の通りになります。 main.go package main import ( "fmt" "time" ) func thread(num int) int { output := 0 for i := 0; i < num; i++ { output += i } time.Sleep(time.Microsecond * 10) return output } func main() { output := make([]int, 100) //スレッドの処理結果格納場所を確保 ch := make(chan bool, 100) //同時に処理できる数 for i := 0; i < 100; i++ { ch <- true go func(num int) { tmp := thread(num) output[num] = tmp <-ch }(i) } for { if len(ch) == 0 { break } time.Sleep(time.Microsecond) } fmt.Println(output) } 現時点では、100スレッドまで同時に処理できるようにできますが、ハードウェアの処理できる数によっては chの確保数を減らせば、同時に処理できる数を変更できます。 また、スレッド内の処理結果の値をメインで使用したい場合は、あらかじめ格納場所は指定してください appendなどの関数を使用すると結果がおかしくなることが多いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む