Go의 팬아웃 패턴을 간단히 살펴보겠습니다. 일반적으로 팬아웃은 여러 작업을 동시에 수행하는 데 사용됩니다.
예를 들어 데이터 파이프라인이 있고 개별 항목을 처리하려고 한다고 가정해 보겠습니다. Go 루틴과 채널을 사용하여 항목을 수신할 때 분할한 다음 개별 항목을 처리할 수 있습니다(예: dB로 입력).
구현하기가 간단한 패턴입니다. 하지만 교착상태를 방지하려면 채널 관리가 필요합니다.
// produce is simulating our single input as a channel func produce(id int) chan int { ch := make(chan int) go func() { for i := 0; i < 10; i++ { ch <- rand.Intn(20) } fmt.Printf("producer %d done\n", id) close(ch) // this is important!!! }() return ch } func worker(id int, jobs chan int, wg *sync.WaitGroup) { for value := range jobs { odd := "even" if (value & 1) == 1 { odd = "odd" } fmt.Printf("worker: %d, got %d is %s\n", id, value, odd) } wg.Done() } func main() { inputCh := produce(1) numWorkers := 3 jobs := make(chan int) // split input into individual jobs go func() { for value := range inputCh { jobs <- value } close(jobs) // this is important!!! }() // fan-out var wg sync.WaitGroup for i := 0; i < numWorkers; i++ { wg.Add(1) go worker(i, jobs, &wg) } wg.Wait() fmt.Println("done") }
여기서 핵심 아이디어는 고정된 수의 작업자가 작업해야 하는 일련의 데이터가 있다는 것입니다.
입력을 위해 일련의 난수를 생성하여 채널에 배치합니다. 우리는 노동자들이 자신의 '일자리'를 가져올 다른 채널로 그들을 옮깁니다.
이 예에서는 입력을 작업 채널로 이동하는 것이 꼭 필요한 것은 아닙니다. 작업자가 입력 채널에서 쉽게 당기도록 할 수도 있습니다. 여기서는 명확성을 위해 이렇게 했습니다.
그런 다음 고정된 수의 작업자를 고루틴으로 실행합니다. 각 작업자는 처리할 데이터가 더 이상 없을 때까지 작업 채널에서 작업을 가져오고, 이때 WaitGroup에 완료되었음을 알립니다.
메인 스레드는 WaitGroup을 사용하여 모든 작업자가 완료될 때까지, 즉 모든 작업이 처리될 때까지 완료되지 않도록 합니다.
이 패턴은 입력 시퀀스 처리 순서를 보장하지 않는다는 점을 언급하는 핵심 사항입니다. 많은 상황에서는 괜찮을 수 있습니다. 예를 들어 입력 시퀀스는 자체 타임스탬프가 포함된 데이터 레코드이며 목표는 레코드를 dB로 저장하는 것입니다. 이 경우 팬아웃은 허용됩니다.
마지막으로, 시퀀스의 모든 데이터가 전송된 후 채널을 닫는 것에 대한 몇 가지 설명을 볼 수 있습니다. 이것은 매우 중요합니다. 채널에서 가져오는 범위 연산자는 더 이상 데이터가 없으면 절전 모드로 전환됩니다. 교착 상태를 발생시키는 close() 문을 한 번 주석 처리하여 이를 확인할 수 있습니다. 고루틴과 채널은 매우 강력하지만 현명하게 사용해야 합니다.
무엇을 다르게 하시겠습니까? 이 예를 어떻게 개선할 수 있나요? 아래에 의견을 남겨주세요.
감사합니다!
이 게시물과 이 시리즈의 모든 게시물에 대한 코드는 여기에서 확인할 수 있습니다.
위 내용은 팬아웃 패턴의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!