goroutine值返回顺序[重复]

This question already has an answer here:

Why following codes always return 2,1, not 1,2.

func test(x int, c chan int) {
   c <- x
}

func main() {
    c := make(chan int)
    go test(1, c)
    go test(2, c)
    x, y := <-c, <-c // receive from c
    fmt.Println(x, y)
}
</div>

If you want to know what the order is, then let your program include ordering information

This example uses a function closure to generate a sequence

The channel returns a struct of two numbers, one of which is a sequence order number

The sequence incrementer should be safe across go routines as there is a mutex lock on the sequence counter

package main

import (
    "fmt"
    "sync"
)

type value_with_order struct {
    v     int
    order int
}

var (
    mu sync.Mutex
)

func orgami(x int, c chan value_with_order, f func() int) {
    v := new(value_with_order)
    v.v = x
    v.order = f()
    c <- *v
}
func seq() func() int {
    i := 0
    return func() int {
        mu.Lock()
        defer mu.Unlock()
        i++
        return i
    }
}

func main() {

    c := make(chan value_with_order)
    sequencer := seq()
    for n := 0; n < 10; n++ {
        go orgami(1, c, sequencer)
        go orgami(2, c, sequencer)
        go orgami(3, c, sequencer)
    }
    received := 0
    for q := range c {
        fmt.Printf("%v
", q)
        received++
        if received == 30 {
            close(c)
        }
    }

}

second version where the sequence is called from the main loop to make the sequence numbers come out in the order that the function is called

package main

import (
    "fmt"
    "sync"
)

type value_with_order struct {
    v     int
    order int
}

var (
    mu sync.Mutex
)

func orgami(x int, c chan value_with_order, seqno int) {
    v := new(value_with_order)
    v.v = x
    v.order = seqno
    c <- *v
}
func seq() func() int {
    i := 0
    return func() int {
        mu.Lock()
        defer mu.Unlock()
        i++
        return i
    }
}

func main() {

    c := make(chan value_with_order)
    sequencer := seq()
    for n := 0; n < 10; n++ {

        go orgami(1, c, sequencer())
        go orgami(2, c, sequencer())
        go orgami(3, c, sequencer())
    }
    received := 0
    for q := range c {
        fmt.Printf("%v
", q)
        received++
        if received == 30 {
            close(c)
        }
    }

}