select

Π’ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ситуациях ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΠΎΡ‚Ρ€Π΅Π±ΠΎΠ²Π°Ρ‚ΡŒΡΡ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ мноТСство go-ΠΏΠΎΠ΄ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌ, ΠΈ ΠΊΠ°ΠΆΠ΄ΡƒΡŽ с собствСнным ΠΊΠ°Π½Π°Π»ΠΎΠΌ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Π΄Π°Π½Π½Ρ‹Ρ…. ΠšΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ взаимодСйствия с Π½ΠΈΠΌΠΈ ΠΌΠΎΠΆΠ½ΠΎ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ инструкции select.

Бинтаксис

select {
    case ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π°Π˜Π»ΠΈΠŸΡ€ΠΈΠ΅ΠΌ1: Π±Π»ΠΎΠΊ1
    ...
    case ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π°Π˜Π»ΠΈΠŸΡ€ΠΈΠ΅ΠΌN: Π±Π»ΠΎΠΊN
    default: Π±Π»ΠΎΠΊD
}

Π’ инструкции select провСряСтся Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ выполнСния ΠΊΠ°ΠΆΠ΄ΠΎΠΉ инструкции ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ ΠΈΠ»ΠΈ ΠΏΡ€ΠΈΠ΅ΠΌΠ°, Π² порядкС свСрху Π²Π½ΠΈΠ·. Если ΠΊΠ°ΠΊΠΈΠ΅-Π½ΠΈΠ±ΡƒΠ΄ΡŒ ΠΈΠ· Π½ΠΈΡ… ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Ρ‹ (Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ Π½Π΅ Π±ΡƒΠ΄ΡƒΡ‚ Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½Ρ‹), ΠΈΠ· Π½ΠΈΡ… ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»ΡŒΠ½ΠΎ выбираСтся ΠΎΠ΄Π½Π° для продолТСния Ρ€Π°Π±ΠΎΡ‚Ρ‹.

Если всС ΠΏΠΎΡ‚ΠΎΠΊΠΈ Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½Ρ‹, Ρ‚ΠΎ, ΠΏΡ€ΠΈ Π½Π°Π»ΠΈΡ‡ΠΈΠΈ Π±Π»ΠΎΠΊΠ° Π² default, Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½ ΠΎΠ½ ΠΈ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π°Ρ инструкция Π·Π° select. Если Π±Π»ΠΎΠΊΠ° default Π½Π΅Ρ‚, Ρ‚ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ Π΄ΠΎΠΆΠΈΠ΄Π°Ρ‚ΡŒΡΡ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ освободившийся ΠΊΠ°Π½Π°Π».

Как Π²Ρ‹Π²ΠΎΠ΄: с default select - Π½Π΅ блокируСтся, Π±Π΅Π· default - блокируСтся.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ 1

Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ 6 Π½Π΅Π±ΡƒΡ„Ρ„Π΅Ρ€Π΅Π·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Ρ… ΠΊΠ°Π½Π°Π»ΠΎΠ², Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ случайным ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ Π² Ρ†ΠΈΠΊΠ»Π΅ Π·Π°ΠΏΠΈΡ…ΠΈΠ²Π°Π΅ΠΌ значСния Π±Π΅Π· ΠΏΠ΅Ρ€Π΅Ρ€Ρ‹Π²Π° (ΠΈ ΠΊΠ°Π½Π°Π»Ρ‹ сразу Π±Π»ΠΎΠΊΠΈΡ€ΡƒΡŽΡ‚ΡΡ)

channels := make([]chan bool, 6)  // array channels
for i := range channels {
    channels[i] = make(chan bool)  // init each channel
}

go func() {
    for {
        channels[rand.Intn(6)] <- true
    }
}

Π‘Ρ‡ΠΈΡ‚Ρ‹Π²Π°Π΅Ρ‚ 36 Π±ΡƒΠ»Π΅Π²Ρ‹Ρ… Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ ΠΈ Π²Ρ‹Π²ΠΎΠ΄ΠΈΠΌ соотв Π½ΠΎΠΌΠ΅Ρ€ ΠΊΠ°Π½Π°Π»Π°

for i := 0; i < 36; i++ {
    var x int
    select {
        case <-channels[0]:
            x = 1
        ...
        case <-channels[5]:
            x = 6        
    }
    fmt.Printf("%d ", x)
}
fmt.Println()

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ 2

Дорогостоящая опСрация

func expensiveComputation(data Data, answer chan int, done chan bool) {
    ...
    finished := false
    for !finished {
        ...
        answer <- result
    }
    done <- true
}

Запуск Π΄Π²ΡƒΡ… дорогостоящих ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ

const allDone = 2
doneCount := 0
answer_a := make(chan int)
answer_b := make(chan int)
defer func() {
    close(answer_a)
    close(answer_b)
}()

done := make(chan bool)
defer func() { close(done) }()

go expensiveComputation(data1, answer_a, done)
go expensiveComputation(data2, answer_b, done)

for doneCount != allDone {
    var which, result int
    select {
        case result = <-answer_a:
            which = 'a'
        case result = <-answer_b:
            which = 'b'
        case <-done:
            doneCount++
    }
    if which != 0 {
        fmt.Print("%c->%d ", which, result)
    }
}

Last updated