# errgroup in golang

By [Primrose](https://paragraph.com/@primrose) · 2023-03-20

---

errgroup
========

go를 쓰다보면 반드시 거치게 되는 루트가 바로 `concurrent programming`이다.

우리는 고루틴을 제어하기 위해서 여러 가지 방법을 쓰는데, 오늘은 errgroup에 대해서 정리해보려고 한다.

우선 일반적으로 `WaitGroup`을 이용해서 제어하는 방법을 보자.

    package main
    
    import "sync"
    
    func main() {
        var wg sync.WaitGroup
        
        wg.Add(1)
        go func() {
            defer wg.Done()
            // do something ...
        }()
        
        wg.Wait()
    }
    

단순히 wg에 작업을 하나 추가하고, 작업이 끝나기를 기다렸다가 마무리하는 코드이다.

그러나 WaitGroup을 쓰다보면 가끔 여러 문제에 부딪힐 때가 있었을 것이다.

WaitGroup의 값이 0이 되도록 컨트롤을 하는데에 실패했다거나, 음수가 되어버린다거나 등등…

사실 동시성을 제대로 제어했다면 일어나지 않을 일이지만, 종종 일어나는 일이긴 하다.

### goroutine with errgroup

`errgroup`은 [golang.org/x/sync](http://golang.org/x/sync) 패키지에 포함되어 있는 4가지의 구현 중 하나이다.

*   `semaphore` : weight가 있는 세마포어.
    
*   `singleflight` - 중복 function call suppression을 지원.
    
*   `syncmap` - map type을 동시적으로 여러 goroutine 내에서 사용할 수 있게 해준다.
    
*   `errgroup` - 하나의 공통적인 작업의 subtask들을 실행하는 goroutine들의 context cancellation, synchronization, 그리고 error propagation을 지원한다.
    

한 번 예제를 보자.

    func main() {
       withContext, ctx := errgroup.WithContext(context.Background())
    }
    

errgroup의 `WithContext` 함수는 컨텍스트 그룹과, 컨텍스트를 반환한다.

`errgroup`은 특히 진행하는 작업들이 에러를 야기하는 경우가 있을 때 사용하기 유용하다.

`errgroup`의 `WithContext`에 기존의 `context`를 전달하면 Group type과 ctx를 리턴한다. 리턴된 Group type으로 goroutine을 시작할 수 있다.

기존에 `go ...` 로 goroutine을 시작하던 부분을 `g.Go(func() ...)` 로 대체할 수 있다. `errgroup`은 goroutine을 실행시키고 해당 goroutine 작업에서 에러가 발생 되는지 지켜본다.

`errgroup`의 장점은 다음과 같다:

1.  `errgroup`을 사용하면 `WaitGroup`을 사용했을 때 처럼 `Add` 나 `Done`을 사용해서 **goroutine들의 수를 직접 조정할 필요가 없다**.
    
2.  goroutine들이 완료될 때까지 `errgroup` 이 알아서 기다리고 에러가 발생하면 어떤 에러가 발생했는지도 `if err:= g.Wait();`을 통해 바로 받아 볼 수 있다.

---

*Originally published on [Primrose](https://paragraph.com/@primrose/errgroup-in-golang)*
