Select 문
Coddy GO 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 107개 중 62번째.
select 문을 사용하면 goroutine이 여러 채널 작업을 동시에 기다릴 수 있습니다. 이는 switch 문과 비슷하지만, 각 case에는 채널 송신 또는 수신이 포함됩니다. 여러 채널을 사용할 준비가 되어 있으면 select는 그중 하나를 무작위로 선택합니다.
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
go func() { ch1 <- "from channel 1" }()
go func() { ch2 <- "from channel 2" }()
select {
case msg1 := <-ch1:
fmt.Println(msg1)
case msg2 := <-ch2:
fmt.Println(msg2)
}
}select가 없으면 ch1에서 수신하는 작업은 데이터가 도착할 때까지 차단되어 ch2의 데이터를 놓칠 수 있습니다. select를 사용하면 데이터를 먼저 수신하는 채널이 처리됩니다.
default case는 select를 논블로킹으로 만듭니다. 어떤 채널도 준비되지 않은 경우 즉시 실행됩니다:
select {
case msg := <-messages:
fmt.Println("Received:", msg)
default:
fmt.Println("No message available")
}일반적인 패턴은 select를 time.After와 함께 사용하여 타임아웃을 설정하는 것입니다. time.After는 지정된 시간이 지나면 값을 수신하는 채널을 반환합니다.
select {
case result := <-ch:
fmt.Println("Got result:", result)
case <-time.After(2 * time.Second):
fmt.Println("Timeout!")
}이를 통해 채널 연산이 끝나지 않을 수 있을 때 프로그램이 영원히 기다리는 것을 방지합니다.
챌린지
쉬움여러 동시 데이터 소스를 처리하기 위해 select 문을 사용하는 서비스 모니터를 만들어 보겠습니다. 모니터는 서로 다른 서비스 채널을 동시에 listen하고, 데이터가 도착하거나 업데이트를 사용할 수 없을 때 appropriate하게 응답합니다.
코드를 두 파일에 걸쳐 구성합니다:
monitor.go: select 기반 채널 처리를 사용하여 서비스 모니터링 로직을 Define합니다.Name(string) 및Status(string) fields를 포함하는ServiceUpdate구조체를 Create합니다.primary chan ServiceUpdate,backup chan ServiceUpdate,done chan bool의 세 채널을 받는Monitorfunction을 Implement합니다. 이 function은 세 채널 모두를 동시에 listen하기 위해select를 사용해야 합니다:primary에서 수신할 때: 형식이 지정된 문자열Primary: [Name] is [Status]를 반환합니다.backup에서 수신할 때: 형식이 지정된 문자열Backup: [Name] is [Status]를 반환합니다.done에서 수신할 때:Monitoring stopped를 반환합니다.
단일
updates chan ServiceUpdate를 받고defaultcase와 함께select를 사용하여 비차단 check를 수행하는CheckStatusfunction을 Implement합니다:- 업데이트를 사용할 수 있는 경우:
Update available: [Name]을 반환합니다. - 업데이트를 사용할 수 없는 경우(default case):
No updates pending를 반환합니다.
main.go: 채널을 설정하고 blocking 및 non-blocking select 동작을 모두 시연합니다.실행할 시나리오를 결정하는 mode을 입력에서 읽습니다:
primary,backup,stop또는check입니다.primary,backup및stopmode의 경우: 서비스 이름과 상태도 읽습니다. 세 채널을 Create하고, mode에 따라 appropriate한 채널로 데이터를 보내는 goroutine을 Launch한 다음Monitor를 호출하고 그 결과를 출력합니다.checkmode의 경우: 서비스 이름과 상태 및 check 전에 데이터를 보낼지 여부를 나타내는 flag(send또는nosend)를 읽습니다. capacity가 1인 buffered channel을 Create합니다. flag가send이면CheckStatus를 호출하기 전에 업데이트를 채널로 보냅니다.CheckStatus의 결과를 출력합니다.
다음 입력이 제공됩니다:
- Line 1: Mode(
primary,backup,stop또는check) - Line 2: 서비스 이름
- Line 3: 서비스 상태
- Line 4(
checkmode에서만):send또는nosend
예를 들어 다음이 주어졌다고 합시다:
primary
Database
healthy출력은 다음과 같아야 합니다:
Primary: Database is healthy그리고 다음이 주어졌다고 합시다:
check
Cache
active
nosend출력은 다음과 같아야 합니다:
No updates pending직접 해보기
package main
import (
"fmt"
)
func main() {
var mode string
fmt.Scanln(&mode)
var serviceName string
fmt.Scanln(&serviceName)
var serviceStatus string
fmt.Scanln(&serviceStatus)
// TODO: 다른 모드 처리: "primary", "backup", "stop", "check"
// "primary", "backup", "stop" 모드의 경우:
// - 세 개의 채널 생성: primary, backup, done
// - 적절한 채널에 데이터를 보내는 고루틴 실행
// - Monitor를 호출하고 결과 출력
// "check" 모드의 경우:
// - 추가 플래그 읽기 ("send" 또는 "nosend")
// - 용량이 1인 버퍼 채널 생성
// - 플래그가 "send"이면 채널에 업데이트 전송
// - CheckStatus를 호출하고 결과 출력
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
8에러 처리와 OOP
error 인터페이스사용자 정의 에러 타입에러 래핑 (fmt.Errorf)센티넬 에러errors.Is()와 errors.As()Panic, Defer, Recover요약 - 파일 파서직접 연습해 보세요: 온라인 Go 컴파일러