2017-01-21 10 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

의 차이는 변형 한, 당신은 다른 조각을 보내는 것입니다 매번 변형 2에서 동일한 슬라이스 (매번 for 루프 위로 생성 된 슬라이스)를 보냅니다. 새로운 슬라이스를 만들지 않고 동일한 슬라이스의 요소를 다른 값으로 설정하면 goroutine은 슬라이스에서 볼 때 어떤 값이 표시되는지를 볼 수 있습니다. 변형 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