Go例程矩阵乘法错误

I am multiplying matrix in parallel using go routines. I am getting index out of range, but when i run the same code sequential it works. (by sequential i mean commenting go line). I am using defer so i do not have to wait for my routines to end as it will be the last thing called

Error D:\0000>go run Ap.go panic: runtime error: index out of range

goroutine 5 [running]:
main.pmultiply(0xc04206c000, 0x3, 0x3, 0xc04206c050, 0x3, 0x3, 0x1, 0x3, 0x0)
        D:/0000/Ap.go:48 +0x95
main.multiply.func1(0xc04206c0a0, 0x3, 0x3, 0xc04200e090, 0xc04200e098, 0xc04206
c000, 0x3, 0x3, 0xc04206c050, 0x3, ...)
        D:/0000/Ap.go:64 +0x94
created by main.multiply
        D:/0000/Ap.go:63 +0x1d7
exit status 2

CODE

package main

import "fmt"

func main(){

    matrix_a := make([][]int,3);

    for i:=0;i<len(matrix_a);i++{

        matrix_a[i]=make([]int,3);

    }


    for i:=0;i<len(matrix_a);i++{

        for j:=0;j<len(matrix_a[0]);j++{
            matrix_a[i][j] = 2;
        }
    }

    matrix_b := make([][]int,3);

    for i:=0;i<len(matrix_b);i++{

        matrix_b[i]=make([]int,3);

    }


    for i:=0;i<len(matrix_b);i++{

        for j:=0;j<len(matrix_b[0]);j++{
            matrix_b[i][j] = 2;
        }
    }

    defer fmt.Println(multiply(matrix_a,matrix_b));

}

func pmultiply(matrix_a [][] int,matrix_b [][] int,row int,col int) int{

    sum := 0;

    for z:=0;z<len(matrix_a[0]);z++{
        sum = sum + matrix_a[row][z] *  matrix_b[z][col];
    }
    return sum;
}

func multiply(matrix_a [][] int,matrix_b [][] int) ([][] int){

    matrix_c := make([][]int,3);

    for i:=0;i<len(matrix_c);i++{
        matrix_c[i]=make([]int,3);
    }

    for i := 0; i < 3; i++ {
        for j := 0; j < 3; j++ {
            go func(){
                matrix_c[i][j] = pmultiply(matrix_a,matrix_b,i,j);
            }()
        }   
    }

    return matrix_c;
}

I see two problems:

  1. You have a classic closure problem in multiply with i and j.
  2. There's no guarantee that matrix_c will be computed before you return it in multiply.

The first one is right here:

for i := 0; i < 3; i++ {
    for j := 0; j < 3; j++ {
        go func(){
            matrix_c[i][j] = pmultiply(matrix_a,matrix_b,i,j);
        }()
    }   
}

The anonymous function is keeping a reference to i and j not the actual values of i and j when you go func() { ... }() so when the goroutine executes, i and j could be any values between zero and three (inclusive). That's where the error you know about comes from: i or j is three because the goroutine is executing after the loops have completed. The easiest solution is to force i and j to be evaluated at the right time:

go func(i, j int) {
    matrix_c[i][j] = pmultiply(matrix_a, matrix_b, i, j)
}(i, j)

The second problem is that the goroutines won't necessarily all finish before you return matrix_c, there's not even a guarantee that any of of them will finish. The easiest solution would be to use a sync.WaitGroup to wait for them to finish. First you'd import "sync", then adjust the loops:

var wg sync.WaitGroup
for i := 0; i < 3; i++ {
    for j := 0; j < 3; j++ {
        wg.Add(1) // Tell the WaitGroup to wait for another thing.
        go func(i, j int) {
            matrix_c[i][j] = pmultiply(matrix_a, matrix_b, i, j)
            wg.Done() // Tell it that we're done.
        }(i, j)
    }
}

and then wait before returning:

wg.Wait()
return matrix_c

Response to Comments: defer doesn't work like that, the specification only says:

A "defer" statement invokes a function whose execution is deferred to the moment the surrounding function returns, either because the surrounding function executed a return statement, reached the end of its function body, or because the corresponding goroutine is panicking.

That's it, it arranges for something to be executed when execution leaves the surrounding function. defer doesn't have anything to do with waiting for threads/goroutines nor does it know anything about goroutines that the deferred function may create.