This is an interesting question, though I don’t believe we should be prescriptive about how web applications are structured - the best structure might vary wildly depending on the app ( an API, a document server, a web app, client & server, multiple services etc). So there will be no one perfect structure for web apps under go. I do think they should be go-gettable, easily bootstrapped if they use a database, use godoc to generate great docs, and structure their apps using packages for bits of functionality that might be shared between web apps, so no ‘models’ or ‘controller’ packages. That means others can easily go get them and get started, and pick out bits of functionality (say auth, currency formatters, or even a comments pkg say) to use it elsewhere.
For what it’s worth, I tend to take a very different approach from the apps you have listed above - a more structured approach based on the urls used to access the application, which hopefully leads to easy discovery, even on much larger apps with 10s of resources. Something like this:
server.go - entrypoint with main(), includes other packages
bin - for binaries
db - for backups, migrations etc
log - for logs
public - the public dir of the website, static resources, compiled resources
secrets - config
src - a set of packages split up by resource, 3rd party and util packages in lib
app - app setup, routes, config, db setup, shared layouts etc
lib - packages for auth, editing, payments, email, so mail.Send etc
users - handles urls under /users
views - templates for users resource
assets - js,css for users compiled from here into public
actions - handlers for users resource
users.go - user model
users_test.go - tests for user model
pages
etc...
This forces you to isolate resources to a greater extent than a shared ‘models’ pkg, and keeps all the functionality, code and resources to do with a given resource in your web app together (like pages, posts, stories, users, etc). Models know nothing about other models. Handlers are in a separate sub-package to let them refer to other models/resources where necessary (for example users actions might join posts or something). Having used rails extensively in the past, a few things I feel it got wrong which should not spread to go:
- Templates and assets like js/css are in a separate folder hierarchy from the views/code they interact with - this is more painful the larger the app gets (same problem with a separate templates folder in go).
- Controllers are bags of actions, which should often be completely independent unrelated handler functions - there is no real need for a ‘controller’ at all, and many rails controllers are almost empty - if so why do they exist? Also, inheritance.
- The framework attempts to do too much behind the scenes (aka magic)
- Addiction to using an ecosystem of gems extending models and rails itself which means many apps glue together too many disparate libraries leading to fragility and dependency hell - this is a danger in go apps as well that try to go down the path of gluing together lots of disparate libraries - I like to vendor most pkgs in lib instead to be clear about dependencies and the keep the number low.
However it did get a lot right (primarily the helpful command line tool I believe), and having a common structure to apps does help you get up to speed quickly in someone else’s app (or even your own if you come back after 6 months), so there is some value in that. It would be really interesting to hear how others have structured their apps and why.