Golang의 Context 패키지
Golang에서는 시스템 리소스를 원활하게 관리할 수 있도록 돕는 Context 패키지를 제공한다. Context를 활용하면 요청이 취소되거나 timeout되었을 때 요청에 대한 모든 goroutine을 종료하고 시스템이 사용중인 리소스를 회수하도록 구성할 수 있게 된다.
서버에 들어오는 요청이 context를 생성하고 서버에서 나가는 호출은 context를 전달받으며 파생된 Context들을 전파하는 방식으로 실행된다. Context에는 데드라인, 취소 요청, 요청 범위 데이터 등이 포함된다. go standard package - context
Context type
Context type은 다음과 같다.
type Context interface
Done
: context에 취소나 timeout이 발생하면 닫히는 채널을 반환한다.Err
: Done 채널이 닫힌 후에 context가 취소된 이유를 나타내는 에러를 반환한다.Deadline
: context가 취소되는 시간을 반환한다.Value
: key와 관련된 값을 반환한다. 요청 범위 데이터 전달에 사용된다.
Derived Context
Background
모든 Context
트리의 루트로 빈 Context를 반환한다. 들어오는 요청의 최상단 Context로 쓰인다.
type emptyCtx struct
type backgroundCtx struct
func Background() Context
WithCancel
func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
type CancelFunc func()
WithCancel
함수로 생성된 Context의 Done
채널은 cancel
함수가 호출되거나 parent.Done
채널이 닫힐 때 닫힌다.
WithDeadline
:
func WithDeadline(parent Context, d Time.time) (Context, CancelFunc)
WithDeadline
함수로 생성된 Context의 Done
채널은 시간이 Deadline에 도달하거나, cancel
함수가 호출되거나, parent.Done
채널이 닫힐 때 닫힌다. 여기서 Deadline은 parent
의 Deadline과 d
중 더 가까운 시간의 값이 사용된다.
WithTimeout
:
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
기본적으로 WithDeadline
과 유사하나, 절대 시간 대신 현재를 기준으로 상대적인 시간을 입력받는다.
WithValue
:
func WithValue(parent Context, key interface, val interface) Context
특정 key에 대해 지정된 값을 반환하는 부모 Context의 복사본을 반환한다.
WithCancelCause
, WithDeadlineCause
, WithTimeoutCause
오류를 가져와 취소 원인으로 기록하는 CancelCauseFunc
을 반환한다.
Context 규칙
Context를 ctx라는 이름의 첫 번째 매개변수로 전달해야 한다. struct 안에 담아서는 안된다.
func DoSomething(ctx context.Context, arg Arg) error
사용될 Context가 사용될 지 불분명하거나 아직 사용할 수 없는 경우 nil context 대신
context.TODO
를 사용하여 전달한다.// context.TODO도 context.Background와 같이 빈 struct를 반환한다. type todoCtx struct func TODO() Context
Context는 여러 고루틴에서 동시에 사용할 수 있다.
프로세스 및 API를 통해 전송되는 요청 범위 데이터에만 Context를 사용한다.
어떻게 코드에 적용할 것인가
WithCancel
package main
import (
"context"
"fmt"
"time"
)
func main()
WithTimeout
package main
import (
"context"
"fmt"
"time"
)
func main()
WithDeadline
package main
import (
"context"
"fmt"
"time"
)
func main()
WithValue
package main
import (
"context"
"fmt"
)
type favoriteContextKey string
func main()