>백엔드 개발 >Golang >Go에서 차단하지 않고 채널 전송 및 수신을 모두 선택할 수 있나요?

Go에서 차단하지 않고 채널 전송 및 수신을 모두 선택할 수 있나요?

Susan Sarandon
Susan Sarandon원래의
2024-10-26 22:34:31959검색

 Can You Select on Both Sending and Receiving Channels in Go, Without Blocking?

조건부 전송 및 수신을 위한 양방향 채널 선택

Go에서는 전송 및 수신 모두에 대해 버퍼링된 채널을 설정할 수 있습니다. 가용성에 따라 선택적 작업을 수행합니다. 다음 시나리오를 고려해보세요.

<code class="go">s := make(chan<- int, 5)
r := make(<-chan int)

버퍼링된 송신 채널 s와 버퍼링되지 않은 수신 채널 r이 있습니다. 질문이 생깁니다: r에 데이터가 있는지 또는 s가 가득 차지 않았는지 확인하기 위해 두 채널을 모두 선택할 수 있습니까? 이는 다음의 기능을 모방하지만 CPU를 100% 소비하지 않습니다.

<code class="go">for {
    if len(s) < cap(s) {
        // Send something
    }
    if len(r) > 0 {
        // Receive something
    }
}</code>

Default Case로 Select 구현

이를 달성하기 위해 다음을 활용할 수 있습니다. 기본 케이스가 있는 select 문. 기본적으로 두 채널 모두 준비되지 않은 경우 불필요한 리소스 소비를 피하기 위해 일시적으로 goroutine을 "휴면"합니다.

<code class="go">s := make(chan<- int, 5)
r := make(<-chan int)

for {
    v := valueToSend() // Value to be sent, evaluated upon each attempt
    select {
    case s <- v:
        fmt.Println("Sent value:", v)
    case vr := <-r:
        fmt.Println("Received:", vr)
    default: // Neither channel is ready, pause briefly
        time.Sleep(time.Millisecond * 1)
    }
}

길이 및 용량 확인이 이상적이지 않은 이유

보내거나 받기 전에 채널의 길이나 용량을 확인하지 않는 것이 중요합니다. 확인하는 시점과 실제 작업 사이에 채널 상태가 변경되어 예기치 않은 차단이 발생할 수 있기 때문입니다. 예를 들면 다음과 같습니다.

<code class="go">if len(r) > 0 {
    // r is ready to receive

    // Other code...

    r <-  // This may block if another goroutine has already received from r!
}</code>

위 내용은 Go에서 차단하지 않고 채널 전송 및 수신을 모두 선택할 수 있나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.