>백엔드 개발 >Golang >Go 채널: `select` 문에서 내 시간 초과가 트리거되지 않는 이유는 무엇입니까?

Go 채널: `select` 문에서 내 시간 초과가 트리거되지 않는 이유는 무엇입니까?

DDD
DDD원래의
2024-12-26 03:37:09404검색

Go Channels: Why Doesn't My Timeout in a `select` Statement Ever Trigger?

Go 채널: 시간 초과가 실행되지 않는 이유

아래 코드 조각처럼 고루틴과 채널이 사용되는 시나리오를 고려해 보세요. 타임아웃 시나리오가 결코 실현되지 않는 이유는 무엇입니까?

func main() {
    c1 := make(chan int, 1)

    go func() {
        for {
            time.Sleep(1500 * time.Millisecond)
            c1 <- 10
        }
    }()

    go func() {
        for {
            select {
            case i := <-c1:
                fmt.Println(i)
            case <-time.After(2000 * time.Millisecond):
                fmt.Println("TIMEOUT") // Not Executed
            }
        }
    }()

    fmt.Scanln()
}

분석

고루틴이 대략 1.5초마다 지속적으로 c1 채널에 값을 전송하기 때문에 타임아웃 시나리오가 발생하지 않습니다. . 타임아웃은 2초 동안 c1에서 값이 수신되지 않은 경우에만 유효합니다.

그러나 c1에서 값을 수신하면 새로운 시간이 됩니다. 후속 선택 실행에서 호출이 이루어진 후 새로운 채널이 생성됩니다. 여기서 값은 2초 후에만 발행됩니다. 이전 선택 실행의 시간 초과 채널이 삭제되어 효과가 없게 됩니다.

해결 방법

이 문제를 해결하려면 시간 초과 채널을 한 번만 생성해야 합니다. 효과적으로:

timeout := time.After(2000 * time.Millisecond)
for {
    select {
    case i := <-c1:
        fmt.Println(i)
    case <-timeout:
        fmt.Println("TIMEOUT") // Will be printed after 2 seconds
    }
}

출력

수정된 코드는 이후에 인쇄됩니다.

10
TIMEOUT
10
10
10
...

따라서 시간 초과 시나리오는 이제 2 이후에 성공적으로 실행됩니다. 초, 의도된 동작을 반영합니다.

위 내용은 Go 채널: `select` 문에서 내 시간 초과가 트리거되지 않는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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