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

Susan Sarandon
풀어 주다: 2024-10-26 22:34:31
원래의
849명이 탐색했습니다.

 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!