The author gave a pretty good reasoning why is it a bad idea, in the same section. However, for the demonstration purposes I think the they should have included their vision on how the request scoped data should be passed.
As I understand they propose to pass the data explicitly, like a struct with fields for all possible request-scoped data.
I personally don't like context for value passing either, as it is easy to abuse in a way that it becomes part of the API: the callee is expecting something from the caller but there is no static check that makes sure it happens. Something like passing an argument in a dictionary instead of using parameters.
However, for "optional" data whose presence is not required for the behavior of the call, it should be fine. That sort of discipline has to be enforced on the human level, unfortunately.
If you use a type like `map[string]any` then yes, it's going to be the same as Context. However, you can make a struct with fields of exactly the types you want.
It won't propagate to the third-party libraries, yes. But then again, why don't they just provide an explicit way of passing values instead of hiding them in the context?
> why don't they just provide an explicit way of passing values instead of hiding them in the context?
Hiding them in a context is the explicit way of passing values through oblivious third-party libraries.
In some future version of Go, it would be nice to just have dynamic scoping. But this works now, and it’s a good pattern. The only real issue is the function-colouring one, and that’s solvable by simply requiring that every exported function take a context.
Precisely because you need to be able to pass it through third party libraries and into callbacks on the other side where you need to recover the values.
Yeah most people talking here are unlikely to have worked on large scale Go apps.
Managing a god-level context struct with all the fields that ever could be relevant and explaining what they mean in position independent ways for documentation is just not scalable at all.
Import cycles mean you’re forced into this if you want to share between all your packages, and it gets really hairy.
As I understand they propose to pass the data explicitly, like a struct with fields for all possible request-scoped data.
I personally don't like context for value passing either, as it is easy to abuse in a way that it becomes part of the API: the callee is expecting something from the caller but there is no static check that makes sure it happens. Something like passing an argument in a dictionary instead of using parameters.
However, for "optional" data whose presence is not required for the behavior of the call, it should be fine. That sort of discipline has to be enforced on the human level, unfortunately.