-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathshipment.go
73 lines (63 loc) · 2.27 KB
/
shipment.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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package context
import (
"context"
"github.com/deixis/spine/contextutil"
)
// Shipment is a just key:value pair that crosses process boundaries
type shipment struct {
next *shipment
key string
val interface{}
}
// WithShipment returns a copy of parent in which the value associated with key
// is val.
//
// Use context Values only for request-scoped data that transits processes and
// APIs, not for passing optional parameters to functions.
//
// The provided key must be comparable and should not be of type
// string or any other built-in type to avoid collisions between
// packages using context. Users of WithValue should define their own
// types for keys. To avoid allocating when assigning to an
// interface{}, context keys often have concrete type
// struct{}. Alternatively, exported context key variables' static
// type should be a pointer or interface.
func WithShipment(parent context.Context, key string, val interface{}) context.Context {
next := shipmentFromContext(parent)
return shipmentWithContext(parent, &shipment{next, key, val})
}
// Shipment returns the shipment associated with this context for key, or nil
// if no value is associated with key. Successive calls to Value with
// the same key returns the same result.
func Shipment(ctx contextutil.ValueContext, key string) interface{} {
for sh := shipmentFromContext(ctx); sh != nil; sh = sh.next {
if sh.key == key {
return sh.val
}
}
return nil
}
// ShipmentRange calls f sequentially for each shipment in the context stack.
// If f returns false, range stops the iteration.
func ShipmentRange(ctx contextutil.ValueContext, f func(key string, value interface{}) bool) {
for sh := shipmentFromContext(ctx); sh != nil; sh = sh.next {
if !f(sh.key, sh.val) {
return
}
}
}
type shipmentKey struct{}
var activeShipmentKey = shipmentKey{}
// shipmentFromContext extracts `Shipment` from context and returns `nil` when
// no instance of `Shipment` can be found
func shipmentFromContext(ctx contextutil.ValueContext) *shipment {
val := ctx.Value(activeShipmentKey)
if o, ok := val.(*shipment); ok {
return o
}
return nil
}
// shipmentWithContext injects `Shipment` to context
func shipmentWithContext(ctx context.Context, sh *shipment) context.Context {
return context.WithValue(ctx, activeShipmentKey, sh)
}