Контекст без отмены распространения - PullRequest
0 голосов
/ 10 января 2019

Как я могу создать копию (если хотите, клона) контекста Go, которая содержит все значения, хранящиеся в оригинале, но не отменяется при оригинале?

Мне кажется, это правильный вариант использования. Скажем, у меня есть http-запрос, и его контекст отменяется после того, как ответ возвращается клиенту, и мне нужно выполнить асинхронную задачу в конце этого запроса в отдельной программе, которая, скорее всего, переживет родительский контекст.

func Handler(ctx context.Context) (interface{}, error) {
        result := doStuff(ctx)
        newContext := howDoICloneYou(ctx)
        go func() {
                doSomethingElse(newContext)
        }()
        return result
}

Кто-нибудь может посоветовать, как это должно быть сделано?

Конечно, я могу отслеживать все значения, которые могут быть помещены в контекст, создавать новый фоновый ctx, а затем просто перебирать каждое возможное значение и копировать ... Но это кажется утомительным и трудным в управлении большая кодовая база.

Ответы [ 2 ]

0 голосов
/ 10 января 2019

Поскольку context.Context - это интерфейс, вы можете просто создать свою собственную реализацию, которая никогда не отменяется:

import (
    "context"
    "time"
)

type noCancel struct {
    ctx context.Context
}

func (c noCancel) Deadline() (time.Time, bool)       { return time.Time{}, false }
func (c noCancel) Done() <-chan struct{}             { return nil }
func (c noCancel) Err() error                        { return nil }
func (c noCancel) Value(key interface{}) interface{} { return c.ctx.Value(key) }

// WithoutCancel returns a context that is never canceled.
func WithoutCancel(ctx context.Context) context.Context {
    return noCancel{ctx: ctx}
}
0 голосов
/ 10 января 2019

Кто-нибудь может посоветовать, как это должно быть сделано?

Да. Не делай этого.

Если вам нужен другой контекст, например, для вашей асинхронной фоновой задачи затем создайте новый контекст. Ваш входящий контекст и один из ваших фоновых задач не связаны , и поэтому вы не должны пытаться повторно использовать входящий.

Если несвязанный новый контекст требует некоторых данных из оригинала: скопируйте то, что вам нужно, и добавьте, что нового.

...