yoongrammer

[Go] context 사용하기 본문

언어/Go 언어

[Go] context 사용하기

yoongrammer 2020. 12. 14. 10:30
728x90

이전 글

2020/12/13 - [언어/Go 언어] - [Go] context 알아보기

 

목차

    [Go] context 사용하기


    context를 사용하면 작업을 취소하거나 중간에 중지할 수 있습니다.

     

    context를 취소하는 방법에는 두 가지 측면이 있습니다.

    1. 취소 이벤트 수신
    2. 취소 이벤트 생성

    취소 이벤트 수신


    context type에서 제공하는 Done() method는 취소 이벤트를 수신하는 역할을 합니다.

    <-ctx.Done()을 사용하여 취소 이벤트를 수신할 때까지 기다리게 할 수 있습니다.

     

    아래 예는 이벤트를 처리하는데 2초가 걸리고 그전에 취소되면 즉시 반환하는 HTTP 서버입니다.

    package main
    
    import (
      "fmt"
      "net/http"
      "time"
    )
    
    func ctxTest(w http.ResponseWriter, r *http.Request) {
      ctx := r.Context()
      fmt.Println("processing request")
    
      select {
      case <-time.After(2 * time.Second):
        w.Write([]byte("request processed"))
      case <-ctx.Done():
        fmt.Println("request cancelled")
      }
    }
    
    func main() {
      http.ListenAndServe("localhost:8000", http.HandlerFunc(ctxTest))
    }

    서버를 실행하고 브라우저에서 localhost : 8000을 열어 테스트할 수 있습니다.

    2초 전에 브라우저를 닫으면 터미널 창에 "request cancelled"이 출력됩니다.

    취소 이벤트 생성


    취소할 수 있는 작업이 있는 경우 context를 통해 취소 이벤트를 생성해야 합니다.

     

    WithCancel 함수를 사용하여 취소 이벤트를 생성할 수 있습니다.

    WithCancel 함수는 파생된 context객체cancel 함수를 반환합니다.

    cancel 함수는 인자를 받지 않고 context를 취소하려고 할 때 호출하면 됩니다.

     

    아래 예는 두 개의 종속 연산을 수행하는 프로그램입니다. 여기서 종속이란 하나가 실패하면 다른 하나가 완료하는 것은 의미가 없음을 의미합니다.

    이 중 하나가 실패하면 모든 종속 작업을 취소하게 됩니다.

    func operation1(ctx context.Context) error {
      time.Sleep(100 * time.Millisecond)
      return errors.New("failed")
    }
    
    func operation2(ctx context.Context) {
      select {
      case <-time.After(500 * time.Millisecond):
        fmt.Println("done")
      case <-ctx.Done():
        fmt.Println("operation2 cancelled")
      }
    }
    
    func main() {
      // Create a new context
      ctx := context.Background()
    
      ctx2, cancel := context.WithCancel(ctx)
    
      go func() {
        err := operation1(ctx2)
        if err != nil {
          cancel()
        }
      }()
    
      operation2(ctx2)
    }

    WithCancel 함수 인자로 context를 전달하기 위해 context.Background() 함수를 사용하여 새로운 context를 생성해야 합니다.

     

    WithCancel 함수를 호출하여 새로운 context와 cancel함수를 반환받습니다.

    새로운 context를 인자로 operation1, operation2 함수에 전달합니다.

    cancel함수를 호출하면 context를 인자로 사용하는 함수들을 취소할 수 있습니다.

     

    operation1 함수는 100ms 이후 실패가 발생하는 함수이고 operation2 함수는 500ms 이후 "done"문구를 출력하는 함수입니다.

    gorutine으로 operation1 함수가 수행되고 100ms 이후 실패하여 cancel() 함수를 호출합니다.

    operation2 함수는 500ms 이전에 operation1 함수 종료에 의해 cancel() 함수가 호출되었기 때문에 "operation2 cancelled" 문구를 출력하고 종료하게 됩니다.

    시간 기반 취소


    서비스가 너무 오래 걸리는 경우 일찍 실패하고 요청을 취소하는 것이 좋습니다.

    WithTimeout, WithDeadline 함수를 사용하여 timeout, deadline을 정할 수 있습니다.

     

    아래는 timeout 시간이 지나면 context를 취소하는 예입니다.

    func main() {
      // Create a new context
      ctx := context.Background()
    
      ctx2, cancel := context.WithTimeout(ctx, 100 * time.Millisecond)
      defer cancel()
    
      select {
      case <-time.After(500 * time.Millisecond):
        fmt.Println("done")
      case <-ctx2.Done():
        fmt.Println("cancelled")
      }
    }

    아래는 deadline 시간이 되면 context를 취소하는 예입니다.

    func main() {
      // Create a new context
      ctx := context.Background()
    
      ctx2, cancel := context.WithDeadline(ctx, time.Now().Add(100*time.Millisecond))
      defer cancel()
    
      select {
      case <-time.After(500 * time.Millisecond):
        fmt.Println("done")
      case <-ctx2.Done():
        fmt.Println("cancelled")
      }
    }

     

     

    참고: https://www.sohamkamani.com/golang/2018-06-17-golang-using-context-cancellation/

    728x90

    '언어 > Go 언어' 카테고리의 다른 글

    [Go] go get 알아보기  (0) 2021.01.11
    [Go] JSON 패키지 알아보기  (0) 2021.01.02
    [Go] context 알아보기  (0) 2020.12.13
    [Go] Modules 사용하기  (0) 2020.12.07
    [Go] Modules 알아보기  (0) 2020.12.06
    Comments