golang context 사용 설명

5800 단어
context 패 키 지 는 단일 요청 을 처리 하 는 여러 goroutine 간 요청 도 메 인 데이터, 취소 신호, 마감 시간 등 과 관련 된 작업 을 간소화 하 는 데 사 용 됩 니 다.
핵심 데이터 구조
type Context interface {
  Deadline() (deadline time.Time, ok bool)
  Done() 

Deadline 은 time. Time 을 되 돌려 줍 니 다. 현재 Context 가 끝나 야 할 시간 입 니 다. ok 은 deadline 이 있 는 지 여 부 를 표시 합 니 다.Done 방법 은 Context 가 취소 되 거나 시간 을 초과 할 때 close channel 을 되 돌려 줍 니 다. close channel 은 방송 알림 으로 context 와 관련 된 함수 에 현재 작업 을 중단 하고 돌아 오 라 고 알려 줍 니 다.Err 방법 은 context 를 되 돌려 줍 니 다. 왜 취소 되 었 습 니까?Value 는 Goroutine 에 데 이 터 를 공유 할 수 있 습 니 다. 물론 데 이 터 를 얻 는 것 은 협 정 안전 합 니 다.그러나 이 데 이 터 를 사용 할 때 동기 화 에 주의해 야 한다. 예 를 들 어 맵 을 되 돌려 주 었 고 이 맵 의 읽 기와 쓰 기 는 자 물 쇠 를 추가 해 야 한다.
cancel 의 context 제공
canceler interface 는 cancel 함 수 를 제공 하 는 context 를 정의 합 니 다.
type canceler interface {
  cancel(removeFromParent bool, err error)
  Done() 

그 기 존의 실현 은 네 가지 가 있다.
emptyCtx:  Context,    Context interface;
cancelCtx:   Context    cancelerinterface
timerCtx:   cancelCtx,      timeout;
valueCtx:         ;

상속 Context
context 패 키 지 는 기 존의 Context 대상 에서 새로운 Context 대상 을 만 드 는 데 도움 을 주 는 함 수 를 제공 합 니 다.이 Context 대상 들 은 하나의 나 무 를 형성 합 니 다. 하나의 Context 대상 이 취소 되면 모든 Context 를 계승 하 는 것 이 취 소 됩 니 다.
Background 는 모든 Context 대상 트 리 의 뿌리 입 니 다. 취소 할 수 없습니다. empty Ctx 의 인 스 턴 스 입 니 다.
var (
background = new(emptyCtx)
)
func Background() Context {
return background
}

Context 생 성 주요 방법
WithCancel
cancelCtx 예제 를 되 돌려 주 고 함 수 를 되 돌려 줍 니 다. 외부 에서 cancelCtx. cancel () 을 직접 호출 하여 Context 를 취소 할 수 있 습 니 다. ` ` `func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { c := newCancelCtx(parent) propagateCancel(parent, &c) return &c, func() { c.cancel(true, Canceled) } }
#### WithDeadline
    cancelCtx  ,       ,         cancelCtx.cancel()   Context。
    ```
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
  c := newCancelCtx(parent)
  propagateCancel(parent, &c)
  return &c, func() { c.cancel(true, Canceled) }
}

WithDeadline
timerCtx 예제 로 돌아 가 구체 적 인 deadline 시간 을 설정 하고 deadline 에 도 착 했 을 때 후대 goroutine 이 종료 합 니 다.
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
  if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {
    return WithCancel(parent)
  }
  c := &timerCtx{
    cancelCtx: newCancelCtx(parent),
    deadline: deadline,
  }
  propagateCancel(parent, c)
  d := time.Until(deadline)
  if d <= 0 {
    c.cancel(true, DeadlineExceeded) // deadline has already passed
    return c, func() { c.cancel(true, Canceled) }
  }
  c.mu.Lock()
  defer c.mu.Unlock()
  if c.err == nil {
    c.timer = time.AfterFunc(d, func() {
      c.cancel(true, DeadlineExceeded)
    })
  }
  return c, func() { c.cancel(true, Canceled) }
}

WithTimeout
WithDeadline 과 마찬가지 로 timerCtx 예 시 를 되 돌려 줍 니 다. 사실은 WithDeadline 이 한 층 을 싸 서 시간의 지속 시간 을 직접 전달 하고 끝 난 후에 종료 합 니 다.
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
  return WithDeadline(parent, time.Now().Add(timeout))
}

WithValue
WithValue 는 valueCtx 에 대응 하고 WithValue 는 Context 에 map 를 설정 합 니 다. 이 Context 와 그 후손 의 goroutine 은 모두 map 의 값 을 얻 을 수 있 습 니 다.
func WithValue(parent Context, key, val interface{}) Context {
  if key == nil {
    panic("nil key")
  }
  if !reflect.TypeOf(key).Comparable() {
    panic("key is not comparable")
  }
  return &valueCtx{parent, key, val}
}

활용 단어 참조
Context 가 가장 많이 사용 되 는 곳 은 Golang 의 웹 개발 에서 http 패키지 의 Server 에서 모든 요청 은 해당 하 는 goroutine 에서 처리 하 는 것 입 니 다.요청 처리 함 수 는 데이터베이스 나 RPC 서비스 와 같은 추가 goroutine 을 시작 합 니 다.요청 을 처리 하 는 goroutine 은 보통 터미널 사용자 의 인증 정보, 인증 과 관련 된 token, 요청 의 마감 시간 등 특정한 데 이 터 를 방문 해 야 합 니 다.요청 이 취소 되 거나 시간 이 초과 되 었 을 때 이 요청 을 처리 하 는 모든 goroutine 은 신속하게 종료 해 야 시스템 에서 이 goroutine 이 차지 하 는 자원 을 방출 할 수 있 습 니 다.비록 우 리 는 외부 에서 어떤 goroutine 을 죽 일 수 없 기 때문에 나 는 그것 을 스스로 끝내 야 한다. 그 전에 우 리 는 channel + select 방식 으로 이 문 제 를 해결 해 야 한다. 그러나 일부 장면 은 실현 하기 가 비교적 번거롭다. 예 를 들 어 하나의 요청 으로 파생 된 각 goroutine 간 에 일정한 제약 관 계 를 만족 시 켜 유효기간, goroutine 트 리 중단 등 을 실현 해 야 한다.전역 변수 요청 같은 기능 을 전달 합 니 다.
컨 텍스트 저장
전체 요청 의 생명주기 에 사용 할 수 있 도록 상하 문 에 모든 종류의 데 이 터 를 저장 할 수 있 습 니 다.
func middleWare(next http.Handler) http.Handler {
  return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
    ctx := context.WithValue(req.Context(),"key","value")
    next.ServeHTTP(w, req.WithContext(ctx))
  })
}
 
func handler(w http.ResponseWriter, req *http.Request) {
  value := req.Context().Value("value").(string)
  fmt.Fprintln(w, "value: ", value)
  return
}
 
func main() {
  http.Handle("/", middleWare(http.HandlerFunc(handler)))
  http.ListenAndServe(":8080", nil)
}

시간 초과 제어
여 기 는 timerCtx 로 함수 의 실행 시간 을 제어 합 니 다. 이 시간 을 초과 하면 중단 할 수 밖 에 없습니다. 그러면 비교적 긴 조작 을 제어 할 수 있 습 니 다. 예 를 들 어 io, RPC 호출 등 입 니 다.
func longRunningCalculation(timeCost int)chan string{
  result:=make(chan string)
  go func (){
  time.Sleep(time.Second*(time.Duration(timeCost)))
    result

엔 딩
context 패 키 지 는 트 리 관 계 를 구축 하 는 Context 를 통 해 이전 Goroutine 에 전달 되 는 다음 Goroutine 에 대한 제어 가 가능 합 니 다.일부 변 수 를 전달 하여 공유 할 수 있 고 시간 초과 도 제어 할 수 있 으 며 여러 Goroutine 의 탈퇴 도 제어 할 수 있 습 니 다.
Google 에 서 는 Golang 프로그래머 에 게 Context 를 첫 번 째 매개 변수 로 입구 요청 과 출구 요청 링크 의 모든 함수 에 전달 해 달라 고 요청 했다 고 합 니 다.이러한 한편 으로 는 여러 팀 이 개발 한 Golang 프로젝트 가 잘 협력 할 수 있 도록 보장 하고 다른 한편 으로 는 간단 한 시간 초과 와 취소 체제 로 임계 구역 데이터 가 서로 다른 Golang 프로젝트 에서 순조롭게 전달 되도록 보장 한다.
그래서 context 를 잘 사용 하 는 것 은 Golang 의 개발, 특히 웹 개발 에 큰 도움 이 됩 니 다.

좋은 웹페이지 즐겨찾기