-
Notifications
You must be signed in to change notification settings - Fork 0
/
local_release.go
53 lines (44 loc) · 1.34 KB
/
local_release.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//go:build release
// +build release
package context
import (
"sync"
)
type locals map[any]any
type localsKey struct{}
// Localize a Context to the current goroutine.
// Any local values set on the Context via WithLocalValue become inaccessible to the returned Context.
func Localize(ctx Context) Context {
var localValues locals
if local, ok := ctx.Value(localsKey{}).(*localCtx); ok {
// Values are shadowed by the local context to prevent access to any locals in a parent context.
local.localsMutex.Lock()
localValues = make(locals, len(local.localValues))
for key, value := range local.localValues {
if localizer, ok := value.(interface{ Localize() any }); ok {
// Use localized value.
localValues[key] = localizer.Localize()
} else {
// Shadowed local value reset to nil.
localValues[key] = nil
}
}
local.localsMutex.Unlock()
} else {
localValues = make(locals, 0)
}
return &localCtx{
Context: ctx,
localsMutex: &sync.RWMutex{},
localValues: localValues,
}
}
// WithLocalValue wraps the parent Context and adds the key-value pair
// as a value local to the current goroutine.
func WithLocalValue(parent Context, key any, value any) {
if local, ok := parent.Value(localsKey{}).(*localCtx); ok {
local.localValues[key] = value
return
}
panic("context not localized to the current goroutine")
}