Golang同時goroutine間通信
Goroutine間でよく使われる通信方式は次のとおりです.グローバル変数 channel contextコンテキスト sync.WaitGroup
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) func WithValue(parent Context, key, val interface{}) Context
サブコンテキストはDoneメソッド(channelを返し、selectで読み取ることができる)を呼び出して、親ノードがcancelを呼び出すかどうかを検出します.上位ノードのcancel呼び出しは、コンテキストツリーのエッジに沿って各サブノードに通知されます.
もちろん、ここでは
sync.WaitGroup
すべてのタスクの完了を単純に待つ場合は、sync.WaitGroup
を使用します.package main
import (
"fmt"
"sync"
"time"
)
func main() {
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go func() {
fmt.Println("func run")
time.Sleep(time.Second)
wg.Done()
}()
}
wg.Wait()
fmt.Println("main done")
}
グローバル変数
簡単ですが、伝達されたデータは一書多読しかできません.package main
import (
"fmt"
"time"
)
var stop bool
func main() {
go f()
time.Sleep(2 * time.Second)
stop = false
time.Sleep(2 * time.Second)
fmt.Println("main done")
}
func f() {
for stop {
fmt.Println("still run")
time.Sleep(time.Second)
}
}
channel
CSP同時プログラミングモデル(Communicating Sequential Process).チャンネルはGolangでコアタイプです.
Golangのselectメカニズムは言語面でLinuxのようなselect機能を実現し、複数のファイル記述子の読み書きイベントを傍受し、イベント発生時にアプリケーション処理をアクティブに通知することができる.Golangのselectはdefaultを設定し、リスニングされたイベントがすべてブロックされたときに実行することもできます.package main
import (
"fmt"
"time"
)
func main() {
stop := make(chan bool)
go f(stop)
time.Sleep(2 * time.Second)
stoptrue
time.Sleep(2 * time.Second)
fmt.Println("main done")
}
func f(stop chan bool) {
for {
select {
case stop:
fmt.Println("done")
return
default:
fmt.Println("still run")
time.Sleep(time.Second)
}
}
}
contextコンテキスト
Golangのコンテキストは木構造であり,context.Background()
法によりコンテキストのルートノードを得ることができる.一般的な方法は次のとおりです.
package main
import (
"fmt"
"sync"
"time"
)
func main() {
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go func() {
fmt.Println("func run")
time.Sleep(time.Second)
wg.Done()
}()
}
wg.Wait()
fmt.Println("main done")
}
簡単ですが、伝達されたデータは一書多読しかできません.
package main
import (
"fmt"
"time"
)
var stop bool
func main() {
go f()
time.Sleep(2 * time.Second)
stop = false
time.Sleep(2 * time.Second)
fmt.Println("main done")
}
func f() {
for stop {
fmt.Println("still run")
time.Sleep(time.Second)
}
}
channel
CSP同時プログラミングモデル(Communicating Sequential Process).チャンネルはGolangでコアタイプです.
Golangのselectメカニズムは言語面でLinuxのようなselect機能を実現し、複数のファイル記述子の読み書きイベントを傍受し、イベント発生時にアプリケーション処理をアクティブに通知することができる.Golangのselectはdefaultを設定し、リスニングされたイベントがすべてブロックされたときに実行することもできます.package main
import (
"fmt"
"time"
)
func main() {
stop := make(chan bool)
go f(stop)
time.Sleep(2 * time.Second)
stoptrue
time.Sleep(2 * time.Second)
fmt.Println("main done")
}
func f(stop chan bool) {
for {
select {
case stop:
fmt.Println("done")
return
default:
fmt.Println("still run")
time.Sleep(time.Second)
}
}
}
contextコンテキスト
Golangのコンテキストは木構造であり,context.Background()
法によりコンテキストのルートノードを得ることができる.一般的な方法は次のとおりです.
package main
import (
"fmt"
"time"
)
func main() {
stop := make(chan bool)
go f(stop)
time.Sleep(2 * time.Second)
stoptrue
time.Sleep(2 * time.Second)
fmt.Println("main done")
}
func f(stop chan bool) {
for {
select {
case stop:
fmt.Println("done")
return
default:
fmt.Println("still run")
time.Sleep(time.Second)
}
}
}
Golangのコンテキストは木構造であり,
context.Background()
法によりコンテキストのルートノードを得ることができる.一般的な方法は次のとおりです.WithCancel
サブコンテキストはDoneメソッド(channelを返し、selectで読み取ることができる)を呼び出して、親ノードがcancelを呼び出すかどうかを検出します.上位ノードのcancel呼び出しは、コンテキストツリーのエッジに沿って各サブノードに通知されます.
package main
import (
"fmt"
"time"
"context"
)
func main() {
ctx, myCancel := context.WithCancel(context.Background())
go func() {
for {
select {
case ctx.Done():
fmt.Println("ctx Done")
return
default:
fmt.Println("goroutine continue")
time.Sleep(time.Second)
}
}
}()
time.Sleep(time.Second * 2)
myCancel()
time.Sleep(time.Second)
fmt.Println("main done")
}
もちろん、ここでは
sync.WaitGroup
を使って睡眠を避けることができます.package main
import (
"fmt"
"time"
"context"
"sync"
)
func main() {
var wg sync.WaitGroup
wg.Add(1)
ctx, myCancel := context.WithCancel(context.Background())
go func() {
for {
select {
case ctx.Done():
fmt.Println("ctx Done")
wg.Done()
return
default:
fmt.Println("goroutine continue")
time.Sleep(time.Second)
}
}
}()
time.Sleep(time.Second * 2)
myCancel()
wg.Wait()
fmt.Println("main done")
}
WithValue
package main
import (
"fmt"
"context"
)
type favContextKey string
func main() {
ctx := context.WithValue(context.Background(), favContextKey("hello"), "Go")
f := func(ctx context.Context, k favContextKey) {
if v := ctx.Value(k); v != nil {
fmt.Println("found value:", v)
return
}
fmt.Println("value not found:", k)
}
f(ctx, favContextKey("hello"))
f(ctx, favContextKey("color"))
}