예제 패키지

예제 패키지

지금까지 배운 문법들이 실제로는 어떻게 한데 묶이는지, 작동하는 완전한 Go 패키지 하나를 보면 훨씬 빨리 감이 잡혀요. 여기 아래에 소수를 찾아내는 **동시성(concurrent) 소수 체(prime sieve)**를 구현한 완전한 Go 패키지가 있습니다.

출처: Go Specification

본문

이 패키지는 generate에서 숫자를 하나씩 보내고, 그 숫자를 filter가 소수로 나눠 걸러내는 방식으로 소수를 차례로 뽑아내요. 채널(chan)을 통해서 값이 흐르고, go 키워드로 각 함수를 별도의 프로세스(고루틴)로 띄워 데이지체인처럼 이어 붙이는 구조죠.

package main

import "fmt"

// Send the sequence 2, 3, 4, … to channel 'ch'.
func generate(ch chan<- int) {
	for i := 2; ; i++ {
		ch <- i  // Send 'i' to channel 'ch'.
	}
}

// Copy the values from channel 'src' to channel 'dst',
// removing those divisible by 'prime'.
func filter(src <-chan int, dst chan<- int, prime int) {
	for i := range src {  // Loop over values received from 'src'.
		if i%prime != 0 {
			dst <- i  // Send 'i' to channel 'dst'.
		}
	}
}

// The prime sieve: Daisy-chain filter processes together.
func sieve() {
	ch := make(chan int)  // Create a new channel.
	go generate(ch)       // Start generate() as a subprocess.
	for {
		prime := <-ch
		fmt.Print(prime, "\n")
		ch1 := make(chan int)
		go filter(ch, ch1, prime)
		ch = ch1
	}
}

func main() {
	sieve()
}

흐름을 한 번 따라가 볼게요. sieve()가 채널 하나를 만들고 generate를 고루틴으로 시작해요. 그러면 generate가 2부터 무한히 숫자를 보내죠. sieve()for 루프에서 채널에서 첫 값을 꺼내면 그게 소수이고, 바로 출력한 뒤 그 소수로 걸러내는 filter를 새로 띄워 채널을 이어 붙여요. 이걸 반복하면서 2, 3, 5, 7… 소수만 남게 되는 원리예요.

더 알아보기

  • 여기서 쓰인 채널(chan) 문법은 채널 타입 섹션에서 더 자세히 다뤄요.
  • go 키워드로 시작하는 고루틴과 프로그램이 실제로 어떻게 실행되는지는 프로그램 초기화와 실행 섹션에서 볼 수 있어요.