I think I responded to everything. Please tell me if I missed something
My initial thought with that many packages was that I could easily swap out one thing for another. For example I could switch from Postgres to MySQL and just had to replace one package and wouldn’t have to change all the API files.
Assuming you aren’t using database specific stuff, this can be done by telling sqlx
to connect differently. This is a one line change. If you really need to support different databases and have database specific stuff, then design an interface with a test suite along with at least two different implementations (e.g., Postgres and MySQL).
But I got one more questions: I want to implement the GET and POST functions for the other models that will be added today but the code will probably nearly be the same as for the users. How can I add those without duplicating the code for everything?
- Implement at least two different models
- Find the patterns between the implementations
- Factor the patterns out into as high-level a component as possible
If the implementations aren’t mostly the same, then there is no duplicated code. If the implementations are small or there will not be many of them, factoring out the common stuff may not be worth it.
So it would be wiser to just duplicate the code and keep it simple?
Sometimes.
One other questions I have concerning nathankerrs reply: I was always taught that the logic should be separated (MVC). Is this not the case in Go or are there different ways to structure the application?
Packages are only one way of organizing code. The same separation that existed before my refactoring exists after it. Packages only help keep things separate by allowing non-exported things to only be directly accessed by things in the package. Note that separate is different than ease of reuse.
From my point of view in Go there are often used too less packages. Often this ends up in large files (In other languages one would call it god object). I mean, one should not put every single thing into a separate package. But a separation by concerns or by business domains is very helpful for structuring the application.
In go, packages and files aren’t objects. Separation of concerns or business domains is done in code. Packages help with separation by not allowing external access to un-exported things (e.g., types, functions, fields) and creating a separate namespace for exported things. Files help with organizing code.
I agree that it is not good to have too many different things happening in a single file or package. I also think it is not good to not group related things together.
Why should exactly the uuid functionality be placed in an own package?
I left the uuid functionality in its own package because it was well separated. If I were writing this program, I would have used someone else’s uuid package, or, because there is only one function, put the implementation in main
(in uuid.go
).