4 ms·
I've experienced both: explicit passing of immutable Contexts in Go and using ThreadLocal storage in Java (DropWizard) apps. I think it was our mistake to use
by georgethomas 6y ago
I've experienced both: explicit passing of immutable Contexts in Go and using ThreadLocal storage in Java (DropWizard) apps.
I think it was our mistake to use ThreadLocal storage for request-specific data. This directly couples threads (which are an OS / scheduling concern) to the serving of requests. We then ran into issues spawning new background threads, or naively switching to Kotlin Coroutines (which can be scheduled on a different thread).
So I prefer the explicit, immutable context passing that Go uses. The `getThing()` pattern you mention seems reasonable and gives you some type safety that is otherwise missing with a bare `context.Value()` calls.
- gravypod 6y agoI think golang is in a unique position to make `ThreadLocal`-like communication-by-state a workable solution due to the go-routine process model. You can get the benefits of imitable-ness + type safety of `ThreadLocal`-ness with some simple maneuvering. This could be accomplished by treating "context" like in-process environment variables. Essentially: 1. My Threadlet Variables are immutable to me. 2. I can create children Threadlets (by default) inherit all of my Threadlet Variables. 3. I can modify the Threadlet Variables of my children Threadlets. This could look something like this (Java + Golang mashup): class User { ... } class UserSingleton implements ThreadletLocal { // implements static set() and static get() and reset() or something } requestMiddleware(request, next) { go next(request), Context.with( UserSingleton.set(extractUserFrom(request.headers)), DeadlineThreadletLocal.within(1 second) ); } This idea is much more refined and further developed in Laravel's facade APIs. They can bind an object dynamically to a "class" and change that underlying implementation dynamically. The benefit of this approach is you can actively distinguish between: 1. who is using your the User class and 2. who is injecting/receiving a User class statically. This allows you to automatically track your "DI". You could also make some syntactic sugar for this like: class UserSettingsController { @ProvidedBy(UserSingleton.class) Optional<User> user; .... some code here who talks to user .... } From a Java perspective I think this should be possible post-Loom.