golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.25k stars 17.57k forks source link

proposal: context: add iterator for values #69562

Open DeedleFake opened 1 week ago

DeedleFake commented 1 week ago

Proposal Details

I could have sworn this was proposed somewhere before, but I looked all over the place and couldn't find it. If it's a duplicate, sorry.

I propose adding a function along the lines of

func AllValues(ctx context.Context) iter.Seq2[any, any]

to the context package that would yield all values accessible via ctx.Value().

ianlancetaylor commented 1 week ago

CC @Sajmani

This doesn't seem like a close fit for the way that context values are handled today. Today you can only access a value if you have a key. There is no way to ask for all the available keys. There isn't much you can usefully do with an arbitrary context key/value pair. In general if you don't know the key ahead of time there is nothing you can do with the value.

So: what would you use this for?

DeedleFake commented 1 week ago

Yeah, I was worried that that would be the response. That's kind of what I wanted it for, though.

The use case is a little weird. I was using contexts to keep track of scoped values alongside cancellation in a toy functional scripting language, essentially. Adding a variable basically means doing ctx = context.WithValue(ctx, Ident(name), val). The idea was that subscopes would add variables to the context and then when the scope exits it would go back to the original context from before the scope. I wanted to be able to enumerate all variables in scope for debugging purposes, mostly, as well as possibly for some metaprogramming features at some point. What I'll probably wind up doing is making my own hierarchical lookup system that just includes a context alongside with Context() context.Context and WithContext(ctx context.Context) Scope methods or something.

If there's a worry about being able to access values directly that weren't available before because of the use of unexported types as keys, maybe an alternative would be to do something like func AllValues[T comparable](ctx context.Context) iter.Seq2[T, any] where it would only yield values with keys of type T. That way it would still be impossible to access values with keys whose types you don't have direct access to.