3 ms·
There's no need to put any dependencies in the context, ever. For HTTP servers, the easiest way is just to use a struct to hold the dependencies: type Serv
by atombender 3y ago
There's no need to put any dependencies in the context, ever. For HTTP servers, the easiest way is just to use a struct to hold the dependencies:
type Server struct {
logger *Logger
users *UserService
// etc.
}
Assuming we use a router like Chi or similar:
router.Get("/users", srv.HandleUsers)
...where HandleUsers is a method on Server.
Some people like to spread handlers in different packages. You can of course declare handlers as functions with no receiver struct, and pass the data as an argument:
router.Get("/users", func(w io.ResponseWriter, r *http.Request) {
userroutes.HandleUsers(srv, w, r)
})
For middlewares, e.g. something that parses a session cookie and fetches the current user, do exactly the same thing.
- Cyph0n 3y agoExactly this. Your dependencies are not request scoped, so there is no reason for them to be included in a per-request context. Instead, dependencies should be passed in to and stored in the struct that uses them. The data you store in the context should be specific to the current request. Think: request ID, user ID, auth info, etc.
- bbkane 3y agoThanks for this perspective - "request scoped" seems like a really good guideline for context data
- floydnoel 3y agoare one-character variables common in Go? every time that i think "maybe i should pick up Go," and then i see the syntax... it gives me pause. seems really ugly!
- kortex 3y agoYes but every time I've seen it, it's in a small scope, it's very obvious the type of the variable and what it's doing. It's really not as bad as it seems once you spend some time in go.
- earthboundkid 3y agoAnd there are a lot of conventions so you know, eg, w is an http.ResponseWriter, r is an http.Request pointer, etc.
- oofta-boofta 3y ago[dead]
- mftb 3y agoChoosing to name variables with a single character has nothing to do with syntax. At most it could be considered idiomatic, but there's no reason to slavishly follow every idiomatic choice, just as there isn't in natural language.
- rendaw 3y agoVariable naming conventions are different from syntax, right? The variables in your own code will be the ones you named. I think this is more prevalent in Go though because go forces you to make many more local variables (since error handling prevents you from composing expressions), and when you need lots of useless local variables for intermediate values with no externally imposed meaning people tend to fall back to things that are easy to write.
- steve_adams_86 3y agoI felt like you did and I totally get it it. It isn’t what it seems like, though. It’s actually very pragmatic and once you embrace it, it makes writing and reasoning about Go much easier than you’d expect. The way you write Go isn’t like most languages I’ve encountered. You write a lot of local variables which typically come from well-named structs and functions, so keeping track of what’s what is extremely low effort. Tracing what something is happens very naturally, and arguably easier because there’s less data to parse. It’s counter intuitive, but I was extremely resistant to it and now I like it (when writing Go) quite a bit. I don’t do this in other languages I write (like TypeScript or Rust); it’s definitely a Go-ism.
- atombender 3y agoThere's a convention to prefer short (1-3 characters) abbreviated identifiers for trivial things. For example, a loop variable: i := 0 But a more complex thing might get a fuller name: producer := NewProducer() In the earlier case with the HTTP handlers, "r" and "w" are conventions. They appear so often that it's counterproductive to give them full names. People who read the code would be confused. Before Go, I did a lot of Java and Ruby, and felt like you did, and went against the conventions. But the code I wrote back when I started with Go now looks foreign to me.
- steve_adams_86 3y agoWow, thanks for this. This nails a nagging problem I was having at my last job. I’d intuitively figured out what was wrong and what a solution might look like, but the way you’ve articulated it here helped crystallize that understanding much better. It’s weird. It isn’t a complex problem or solution, but almost every team I’ve worked on hasn’t done this. You get to this point where you’ve seen so much context-stuffing that you half expect to see tools to help you do it in the standard library. You almost wonder if your aversion to it is because you’re the crazy one, haha.