2017-01-21 6 views
0

私はGo言語が比較的新しいです。私はそうは望みませんが、愚かな質問であなたを悩ますかもしれません。ちょうど私のお詫び申し訳ありません。スライスタイプの入出力チャネルを使用して並行作業ルーチンを実行してください

これは私の例です:main()から呼び出されるworker()関数を並行Goルーチンのセットとして定義しました。入力データと出力データはスライスタイプ[] intの両方の入力チャネルと出力チャネルを介して提供されます。あるケースでは、すべてが期待どおりに動作し、他のケースでは結果が不良です。コードのコメントとコードの下のプログラムの出力を参照してください。

正直なところ、私は両方のコードバリエーションの実際の違いはわかりません。私はここで何を欠場したのですか?アドバイスありがとうございます!

package main 

import "fmt" 
import "runtime" 

func worker(x_ch <-chan []int, y_ch chan<- []int, wid int) { 

    for x := range x_ch { 
     y := x 
     fmt.Println(" worker", wid, "x:", x) 
     fmt.Println(" worker", wid, "y:", y) 
     y_ch <- y 
    } 
} 

func main() { 

    n_workers := runtime.NumCPU() 
    n_len := 4 
    n_jobs := 4 
    x := make([]int, n_len) 
    x_ch := make(chan []int, 10) 
    y_ch := make(chan []int, 10) 

    for j := 0; j < n_workers; j++ { go worker(x_ch, y_ch, j) } 

    for k := 0; k < n_jobs; k++ { 

//  variant 1: works! 
     x = []int{k, k, k, k} 

//  variant 2: doesn't work! 
//  for i := range x { x[i] = k } 

     fmt.Println("main x:", k, x) 
     x_ch <- x 
    } 

    close(x_ch) 

    for i := 0; i < n_jobs; i++ { 
     z := <- y_ch 
     fmt.Println("  main y:", i, z) 
    } 
} 

正しい出力(変種1):

main x: 0 [0 0 0 0] 
main x: 1 [1 1 1 1] 
main x: 2 [2 2 2 2] 
main x: 3 [3 3 3 3] 
    worker 3 x: [3 3 3 3] 
    worker 3 y: [3 3 3 3] 
    worker 2 x: [2 2 2 2] 
    worker 2 y: [2 2 2 2] 
    worker 1 x: [0 0 0 0] 
    worker 1 y: [0 0 0 0] 
    worker 0 x: [1 1 1 1] 
    worker 0 y: [1 1 1 1] 
     main y: 0 [3 3 3 3] 
     main y: 1 [2 2 2 2] 
     main y: 2 [0 0 0 0] 
     main y: 3 [1 1 1 1] 

間違った出力(バリアント2):

main x: 0 [0 0 0 0] 
main x: 1 [1 1 1 1] 
main x: 2 [2 2 2 2] 
main x: 3 [3 3 3 3] 
    worker 3 x: [3 3 3 3] 
    worker 3 y: [3 3 3 3] 
     main y: 0 [3 3 3 3] 
    worker 0 x: [2 2 2 2] 
    worker 0 y: [3 3 3 3] 
     main y: 1 [3 3 3 3] 
    worker 1 x: [1 1 1 1] 
    worker 1 y: [3 3 3 3] 
     main y: 2 [3 3 3 3] 
    worker 2 x: [3 3 3 3] 
    worker 2 y: [3 3 3 3] 
     main y: 3 [3 3 3 3] 

答えて

1

違いは、バリアント1で、あなたは別のスライスを送っているということですたびに変種2では、毎回同じスライスを送信しています(forループの上に作成されたスライス)。新しいスライスを作成せずに、同じスライスの要素を異なる値に設定するだけで、ゴルーチンはスライスを見るときにそのスライス内に何らかの値が存在するかどうかを確認します。変形2では、mainはループを4回過ぎた後の最終値なので、常に[3 3 3 3]と表示されます。スライスオブジェクトの値には、要素自体ではなく、基になる要素への参照が含まれます。スライスの説明はhereです。

0

あなたの説明のためにありがとう、今どこに問題があるかわかります。 Iを出力するポインタアドレスをいくつかのデバッグコードを追加し、結果は(slighty再フォーマット出力で)である:

バリアント1:

main 0 x=[0 0 0 0] &x=0x1830e180 &x[0]=0x1830e1e0 
main 1 x=[1 1 1 1] &x=0x1830e180 &x[0]=0x1830e230 
main 2 x=[2 2 2 2] &x=0x1830e180 &x[0]=0x1830e270 
main 3 x=[3 3 3 3] &x=0x1830e180 &x[0]=0x1830e2a0 
    worker 3 x=[3 3 3 3] &x=0x1830e1d0 &x[0]=0x1830e2a0 
    worker 3 y=[3 3 3 3] &y=0x1830e2e0 &y[0]=0x1830e2a0 
     main 0 y=[3 3 3 3] &y=0x1830e2d0 &y[0]=0x1830e2a0 
    worker 0 x=[0 0 0 0] &x=0x1830e1a0 &x[0]=0x1830e1e0 
    worker 0 y=[0 0 0 0] &y=0x1830e370 &y[0]=0x1830e1e0 
     main 1 y=[0 0 0 0] &y=0x1830e360 &y[0]=0x1830e1e0 
    worker 1 x=[1 1 1 1] &x=0x1830e1b0 &x[0]=0x1830e230 
    worker 1 y=[1 1 1 1] &y=0x1830e400 &y[0]=0x1830e230 
     main 2 y=[1 1 1 1] &y=0x1830e3f0 &y[0]=0x1830e230 
    worker 2 x=[2 2 2 2] &x=0x1830e1c0 &x[0]=0x1830e270 
    worker 2 y=[2 2 2 2] &y=0x1830e480 &y[0]=0x1830e270 
     main 3 y=[2 2 2 2] &y=0x1830e470 &y[0]=0x1830e270 

バリアント2:

main 0 x=[0 0 0 0] &x=0x1830e180 &x[0]=0x1830e190 
main 1 x=[1 1 1 1] &x=0x1830e180 &x[0]=0x1830e190 
main 2 x=[2 2 2 2] &x=0x1830e180 &x[0]=0x1830e190 
main 3 x=[3 3 3 3] &x=0x1830e180 &x[0]=0x1830e190 
    worker 3 x=[3 3 3 3] &x=0x1830e1d0 &x[0]=0x1830e190 
    worker 3 y=[3 3 3 3] &y=0x1830e2a0 &y[0]=0x1830e190 
     main 0 y=[3 3 3 3] &y=0x1830e290 &y[0]=0x1830e190 
    worker 0 x=[3 3 3 3] &x=0x1830e1a0 &x[0]=0x1830e190 
    worker 0 y=[3 3 3 3] &y=0x1830e330 &y[0]=0x1830e190 
     main 1 y=[3 3 3 3] &y=0x1830e320 &y[0]=0x1830e190 
    worker 1 x=[3 3 3 3] &x=0x1830e1b0 &x[0]=0x1830e190 
    worker 1 y=[3 3 3 3] &y=0x1830e3c0 &y[0]=0x1830e190 
     main 2 y=[3 3 3 3] &y=0x1830e3b0 &y[0]=0x1830e190 
    worker 2 x=[3 3 3 3] &x=0x1830e1c0 &x[0]=0x1830e190 
    worker 2 y=[3 3 3 3] &y=0x1830e440 &y[0]=0x1830e190 
     main 3 y=[3 3 3 3] &y=0x1830e430 &y[0]=0x1830e190 
関連する問題