GoLang Context 패키지 상세 설명
프로필
Context 는 go 에서 자주 사용 되 는 패키지 로 구 글 이 공식 개발 했다.특히 흔히 볼 수 있 는 응용 장면 은 하나의 요청 이 파생 된 각 goroutine 간 에 일정한 제약 조건 을 만족 시 켜 유효기간, routline 트 리 종료, 전체 변 수 를 전달 하 는 등 기능 을 실현 해 야 한다.Context 를 사용 하여 컨 텍스트 기능 을 실현 하려 면 매개 변 수 를 입력 하 는 첫 번 째 context. context 형식의 변 수 를 입력 해 야 합 니 다. 우 리 는 소스 코드 의 읽 기와 예제 코드 를 통 해 context 의 용법 을 설명 할 것 입 니 다.
핵심 인터페이스\# #
type Context interface {
Deadline() (deadline time.Time, ok bool)
Done()
기본 오류:
var Canceled = errors.New("context canceled")
var DeadlineExceeded error = deadlineExceededError{}
type deadlineExceededError struct{}
func (deadlineExceededError) Error() string { return "context deadline exceeded" }
func (deadlineExceededError) Timeout() bool { return true }
func (deadlineExceededError) Temporary() bool { return true }
빈 Context
// An emptyCtx is never canceled, has no values, and has no deadline. It is not
// struct{}, since vars of this type must have distinct addresses.
type emptyCtx int
func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
return
}
func (*emptyCtx) Done()
원본 패키지 에서 두 개의 빈 Context 를 제공 합 니 다.
var (
background = new(emptyCtx)
todo = new(emptyCtx)
)
// Background returns a non-nil, empty Context. It is never canceled, has no
// values, and has no deadline. It is typically used by the main function,
// initialization, and tests, and as the top-level Context for incoming
// requests.
func Background() Context {
return background
}
// TODO returns a non-nil, empty Context. Code should use context.TODO when
// it's unclear which Context to use or it is not yet available (because the
// surrounding function has not yet been extended to accept a Context
// parameter). TODO is recognized by static analysis tools that determine
// whether Contexts are propagated correctly in a program.
func TODO() Context {
return todo
}
canceler##
cancelCtx 구조 체 는 Context 를 계승 하여 canceler 방법 을 실현 했다.
//*cancelCtx *timerCtx canceler , cancel
// A canceler is a context type that can be canceled directly. The
// implementations are *cancelCtx and *timerCtx.
type canceler interface {
cancel(removeFromParent bool, err error)
Done()
cancel 과 관련 된 방법 을 살 펴 보 겠 습 니 다.
type CancelFunc func()
// WithCancel parent Context , cancel Context Done channel
// cancel ( )
// parent cancel ,
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
c := newCancelCtx(parent)
propagateCancel(parent, &c)
return &c, func() { c.cancel(true, Canceled) }
}
func newCancelCtx(parent Context) cancelCtx {
return cancelCtx{
Context: parent,
done: make(chan struct{}),
}
}
// cancel
// parent ( parent), cancel parent
// parent cancel, child cancel
// , child parent children (Context , , )
//
// cancel parent, cancel, goroutine parent , cancel child , child 。
func propagateCancel(parent Context, child canceler) {
if parent.Done() == nil {
return // parent is never canceled
}
if p, ok := parentCancelCtx(parent); ok {
p.mu.Lock()
if p.err != nil {
// parent has already been canceled
child.cancel(false, p.err)
} else {
if p.children == nil {
p.children = make(map[canceler]bool)
}
p.children[child] = true
}
p.mu.Unlock()
} else {
go func() {
select {
case
Deadline 과 TimeOut 은 먼저 cancelCtx 를 계승 하 는 구조 체 를 봅 니 다.
type timerCtx struct {
cancelCtx // cancelCtx ,cancelCtx.Context
timer *time.Timer // Under cancelCtx.mu.
deadline time.Time
}
func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
return c.deadline, true
}
func (c *timerCtx) String() string {
return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now()))
}
// cencelCtx , cancelCtx.cancel, c.timer Stop(), c.timer=nil
func (c *timerCtx) cancel(removeFromParent bool, err error) {
c.cancelCtx.cancel(false, err)
if removeFromParent {
// Remove this timerCtx from its parent cancelCtx's children.
removeChild(c.cancelCtx.Context, c)
}
c.mu.Lock()
if c.timer != nil {
c.timer.Stop()
c.timer = nil
}
c.mu.Unlock()
}
이 구조 체 에서 파생 된 두 가지 방법:
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
// parent deadline deadline , WithCancel, deadline , deadline 。
if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {
// The current deadline is already sooner than the new one.
return WithCancel(parent)
}
c := &timerCtx{
cancelCtx: newCancelCtx(parent),
deadline: deadline,
}
//
propagateCancel(parent, c)
// , cancel
d := deadline.Sub(time.Now())
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 {
// cancel , deadline cancel
c.timer = time.AfterFunc(d, func() {
c.cancel(true, DeadlineExceeded)
})
}
return c, func() { c.cancel(true, Canceled) }
}
// timeout deadline
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
return WithDeadline(parent, time.Now().Add(timeout))
}
Value Value Ctx 는 주로 메타 데 이 터 를 전달 하 는 데 사 용 됩 니 다. WithValue () 를 통 해 계승 을 전달 하고 Value () 를 통 해 읽 습 니 다. 간단 하고 군말 하지 않 습 니 다.
func WithValue(parent Context, key interface{}, val interface{}) Context {
return &valueCtx{parent, key, val}
}
type valueCtx struct {
Context
key, val interface{}
}
func (c *valueCtx) String() string {
return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val)
}
func (c *valueCtx) Value(key interface{}) interface{} {
if c.key == key {
return c.val
}
return c.Context.Value(key)
}
사용 원칙:\#\#
func DoSomething(ctx context.Context, arg Arg) error {
... use ctx ...
}
사실 그 자체 가 매우 간단 합 니 다. 이 가방 을 가 져 온 후에 Context 대상 을 초기 화하 고 모든 자원 접근 방법 에서 호출 한 다음 에 사용 할 때 Context 대상 이 Cancel 에 있 는 지 확인 하고 바 인 딩 된 자원 을 방출 합 니 다.다음 과 같다.http://blog.golang.org/context예제 프로그램) 최종 cancel 을 초기 화하 고 설정 합 니 다.
func handleSearch(w http.ResponseWriter, req *http.Request) {
// ctx is the Context for this handler. Calling cancel closes the
// ctx.Done channel, which is the cancellation signal for requests
// started by this handler.
var (
ctx context.Context
cancel context.CancelFunc
)
timeout, err := time.ParseDuration(req.FormValue("timeout"))
if err == nil {
// The request has a timeout, so create a context that is
// canceled automatically when the timeout expires.
ctx, cancel = context.WithTimeout(context.Background(), timeout)
} else {
ctx, cancel = context.WithCancel(context.Background())
}
defer cancel() // Cancel ctx as soon as handleSearch returns.
중간 과정 에서 전달 하고 자원 관련 작업 을 할 때 ctx. Done () 에서 값 이 전달 되 었 는 지 판단 하 며 Done () 의 사용 에 대해 참고 해 야 합 니 다.http://blog.golang.org/pipelines 예상 치 못 하 게 끝 난 프로그램의 반환 값 은 대응 하 는 ctx. Err () 여야 합 니 다.
func httpDo(ctx context.Context, req *http.Request, f func(*http.Response, error) error) error {
// Run the HTTP request in a goroutine and pass the response to f.
tr := &http.Transport{}
client := &http.Client{Transport: tr}
c := make(chan error, 1)
go func() { c
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.