Golang極簡入門チュートリアル(3):同時サポート

5793 ワード

この文章は主にGolang極簡入門チュートリアル(3):同時サポートを紹介し、goroutineスレッド、channelオペレータなどの内容を説明し、必要な友达は参考にすることができます.
Golangランタイム(runtime)はgoroutineと呼ばれる軽量レベルのスレッドを管理しています.数十万級のgoroutineを作成するのは問題ありません.例:
 
    
package main
 
import (
    "fmt"
    "time"
)
 
func say(s string) {
    for i := 0; i < 5; i++ {
        time.Sleep(100 * time.Millisecond)
        fmt.Println(s)
    }
}
 
func main() {
    // goroutine say
    go say("world")
    say("hello")
}

私たちはchannelとgoroutine通信を使用します.channelは、特定のタイプの値を受信および送信するために使用されるタイプのチャネルである.オペレータ
 
    
// v channel ch
ch // channel ch v
v :=

channelとgoroutine通信を使用すると、ロックメカニズムを明示的に使用することを避けることができ、channelを介して値を送信および受信するときにデフォルトでブロックされます.
make関数によるchannelの作成:
 
    
// int channel int
ch := make(chan int)

完全な例:
 
    
package main
 
import "fmt"
 
// a
func sum(a []int, c chan int) {
    sum := 0
    for _, v := range a {
        sum += v
    }
    // channel c
    c }
 
func main() {
    a := []int{7, 2, 8, -9, 4, 0}
 
    // channel c
    c := make(chan int)
 
    go sum(a[:len(a)/2], c)
    go sum(a[len(a)/2:], c)
 
    // goroutine
    x, y :=  
    fmt.Println(x, y, x+y)
}package main
 
import "fmt"
 
// a
func sum(a []int, c chan int) {
    sum := 0
    for _, v := range a {
        sum += v
    }
    // channel c
    c }
 
func main() {
    a := []int{7, 2, 8, -9, 4, 0}
 
    // channel c
    c := make(chan int)
 
    go sum(a[:len(a)/2], c)
    go sum(a[len(a)/2:], c)
 
    // goroutine
    x, y :=  
    fmt.Println(x, y, x+y)
}

channelは、渡された値をキャッシュするためにバッファ(buffer)を持つことができ、channelに送信されるとバッファがいっぱいになる場合にのみブロックされ、channelの値を受信するとバッファが空いている場合にのみブロックされます.
 
    
package main
 
import "fmt"
 
func main() {
    // channel, 2
    c := make(chan int, 2)
    // channel 2
    //
    c     c     fmt.Println(     fmt.Println( }

送信者はcloseを呼び出してchannelを閉じることができ、受信者はchannelが閉じるかどうかを検出することができる.
 
    
// ok false , channel
v, ok :=

閉じたchannelに値を送信しないでください(will cause a panic).
for rangeを使用してchannelの値を受信できます.
 
    
package main
 
import "fmt"
 
func fibonacci(n int, c chan int) {
    x, y := 0, 1
    for i := 0; i < n; i++ {
        c         x, y = y, x+y
    }
    // c
    close(c)
}
 
func main() {
    c := make(chan int, 10)
    go fibonacci(cap(c), c)
    // for range
    // c
    for i := range c {
        fmt.Println(i)
    }
}

通常、チャネルをアクティブに閉じる必要はありません.しかし、受信者は、受信できる値がないことを通知されなければならない場合があります.この場合、forrangeループを終了するなど、アクティブに閉じる必要があります.
select文を使用すると、1つのgoroutineが複数の通信操作を待つことができます.selectは、caseが実行できるまでブロックされます.実行可能なものが複数ある場合は、ランダムに1つ選択されます.
 
    
package main
 
import "fmt"
 
func fibonacci(c, quit chan int) {
    x, y := 0, 1
    for {
        select {
        case c             x, y = y, x+y
        //
        case             fmt.Println("quit")
            return
        }
    }
}
 
func main() {
    c := make(chan int)
    quit := make(chan int)
    go func() {
        for i := 0; i < 10; i++ {
            fmt.Println(         }
        quit     }()
    fibonacci(c, quit)
}

selectのdefaultは、caseが実行できない場合に実行されます(switchと同様).
 
    
package main
 
import (
    "fmt"
    "time"
)
 
func main() {
    // tick channel
    // 100 tick channel
    tick := time.Tick(100 * time.Millisecond)
    // boom channel
    // 500 boom channel
    boom := time.After(500 * time.Millisecond)
    for {
        select {
        case             fmt.Println("tick.")
        case             fmt.Println("BOOM!")
            return
        default:
            fmt.Println("    .")
            time.Sleep(50 * time.Millisecond)
        }
    }
}