package main import ( "context" "fmt" ) // 정수 제너레이터 func Range(ctx context.Context) <-chan int { cho := make(chan int) go func() { defer close(cho) for i := 2; ; i++ { select { case cho <- i: case <-ctx.Done(): return } } }() return cho } // 배수 걸러주는 파이프 func FilterMultiples(n int) func(context.Context, <-chan int) <-chan int { return func(ctx context.Context, chi <-chan int) <-chan int { cho := make(chan int) go func() { defer close(cho) for x := range chi { if x%n == 0 { continue } select { case cho <- x: case <-ctx.Done(): return } } }() return cho } } func MakePrimes(ctx context.Context) <-chan int { cho := make(chan int) go func() { defer close(cho) chn := Range(ctx) for { select { case n := <-chn: chn = FilterMultiples(n)(ctx, chn) // 배수 걸러주는 파이프를 동적 연결 select { case cho <- n: case <-ctx.Done(): return } case <-ctx.Done(): return } } }() return cho } func PrintPrimes(max int) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() for prime := range MakePrimes(ctx) { if prime > max { break } fmt.Println(prime) } } func main() { PrintPrimes(100) }



제너레이터 -> 2

제너레이터 -> 2n 파이프 -> 3

제너레이터 -> 2n 파이프 -> 3n 파이프 -> 5

제너레이터 -> ... -> 소수 x

제너레이터 -> ... -> xn 파이프 -> 소수 y

y가 max 넘으면 context 이용해 종료



멋지지 않냐. 모 입문책에서 발췌.