3 ms·
Aren't contexts supposed to flow mutations down the call stack, not up it?
by zmj 6y ago
Aren't contexts supposed to flow mutations down the call stack, not up it?
- nkozyra 6y agoThat was my first impression and why I guessed nil value.
- travmatt 6y agoMy second thought was that go will pass the struct by value, so even if it didn’t crash that member would not have been set in the parent function.
- TheDong 6y agoSince the argument is "context.Context", an interface type, it's not necessarily passing a value. It is actually a pointer since the implementation, if you look at the definition of `context.TODO()`, is of type `* context.emptyContext`. Looking at just a function definition, you can't know if a variable is a value or a pointer unless you first determine if it's an interface type, and if it is an interface type, you have to know the concrete type of the caller to know. However, even a struct passed by value can be mutated since interior mutability can be managed with internal pointers. For example: type value struct { interior *int } func(v value) mutate(to int) { *v.interior = to } func(v value) String() string { return fmt.Sprintf("%d", *v.interior) } func newValue(i int) value { return value{&i} } func mutateValue(v value, to int) { v.mutate(to) } func main() { val := newValue(10) mutateValue(val, 20) fmt.Println(val) }
- tsimionescu 6y agoAren't all interface variables pointers in Go, regardless of whether the type implementing the interface is a pointer or a value?
- morelisp 6y agoInterfaces are internally pointers, insofar as the value passed when you pass around an interface is a pointer to something so that the value passed is a fixed size regardless of the underlying type (otherwise you couldn't have any arrays of interfaces). But if the interface is implemented by a pointer-to-T and you pass a T, you will get an error; and if you have wrapped a T in one interface and try to convert it to another interface that is only satisfied by a pointer-to-T, the conversion will fail. So the answer to "are interfaces are always pointers?" is yes if you're asking about implementing the Go compiler or worried about the size of some allocation; but no if you are asking about Go's type system.
- eternalban 6y agoAnd if the functions in question were properly named func NewWithValue(parent Context, key, val interface{}) Context func NewBackground() Context you wouldn't even have to guess.
- masklinn 6y agoIDK, having never seen or used Go's contexts, the `With` prefix immediately made me think that it likely created a new context: it's a common naming convention in Rust or Python. I'd have expected `SetValue` for updating keys in-place. That `WithValue` creates an "inheritance" relationship surprised me a lot more, that I did not expect.
- morelisp 6y ago`context.Background()` doesn't allocate anything, it gives you the runtime's singular top-level context.