if not in constructor, where does one setup the server dependencies then? especially dependencies that need to be mocked up in tests. true, having to explicitly provide dependencies is bothersome but it’s the only way i can think of without magic dependencies and untestable behavior.
You pass them in to the constructor (as mentioned in the talk, only practical if there are just a few), or initialize the server struct directly and assign them later, or create a dependencies public struct that you pass in (e.g. MyServer.New(MyServer.Deps{DB: dbconn, SomeClient: client})). In New(), there is code to do things like setup routes - very specific initialization to your service. You want to run that in your unit tests, and so you don't want to mix in initializing services in there because if you do it's harder/impossible to test. There are some "Clean Code Talks" from about a decade ago here on YT that explain the value of that approach - you don't build a car and expect it to build an engine for itself - you build an engine and a car and give it to the car in your setup. It helps for testability to move initialization as far up the call chain as you can. So your main module usually does a lot of the boring initialization of things, all in one place where all the dependencies are clear. It also simplifies refactoring like he mentioned breaking a big service into separate services. Give the db connection to the small services and give the small services to the main server.
This video is great, but as a real newby to Golang I'm confused on a few points. At 27:55, what does this accomplish? Are these structs used inside the handler function somewhere?
the request struct is used to unmarshall the request body of the request, the response struct to fill the response and then encode it in json and write to response writer, they will be used by that returned HandlerFunc.
This is a common practice when writing an API endpoint, to take a serialized request and return a serialized response (e.g a JSON string in the body), and mapping these to structs and doing validation and deserialization once before handling business logic. Here's an example some might find useful: www.alexedwards.net/blog/how-to-properly-parse-a-json-request-body