Thanks for all the suggestions everyone, I appreciate it. I've been experimenting so here are some comments:
And I must stress -- do not start your project with folders "services",
"models", "views" ... etc. it's a brain dead way to bootstrap a project
and only makes you feel good, because it looks like you have something
of value; in reality you don't... It's like when you try to design a
house and you start by creating 4 boxes, here go the sockets, here the
walls, here windows, here electrical -- you lose the building as a whole,
because you are mechanically separating things by form and similarity
-- rather than figuring out how to create the rooms such that they
support each other and function well together.
Other than a handlers package and a server package (which make sense, since my application needs a server and handlers to work),
Your application doesn't need "handlers", your application needs some specific functionality. a way to manage users... "handler" part is an annoying implementation detail.
I know this looks like splitting hairs, but, the end-user won't care about the "handlers" -- hence you really shouldn't care that much about them either. Imagine going to a customer and saying... "Hey, I just implemented handlers"... the customer will just ask, "What, that's not what I asked for? Why am I paying you money?".
the remaining packages are business-oriented,
It's not about being "business-oriented" -- it's about understanding what is the value and what are the pieces that really matter in providing the value.
don't worry (e.g. models live with their respective service). I still need services though (you can call them something else) to handle e.g. authentication.
You might need an abstraction layer or a boundary, but not necessarily "services".
The way you think will highly correlate how you structure your code. I know these seem like minor points, but these things end up as accidental complexities in your code. I see that you feel that something is wrong with the code -- hence the question. And it seems the same feeling I had, things simply didn't want to fit together.
The major concern here is that you are flipping the "abstraction layer order" and hence end up mixing lower-level details with the higher level goals.
My question was more related to organizing these packages that aren't necessarily static. Although my application needs an authentication package, the actual service that this package uses (i.e. what implements the package's public-facing interface) can be implemented in many different ways, and I'd like for client code to be able to use them "nicely" (hence the MySQL example).
Anyways, to make the discussion more concrete - what exactly are you implementing and why does the end-user care about your web-app?
For simplicity let's call it "thingy", one possibility:
cmd/thingy-server --> pulls the
cmd/thingy-server/user --> "user.Page", (implement an handler and uses thingy.DB)
cmd/thingy-server/home --> "home.Page"
cmd/thingy-server/admin --> "admin.Page"
db.go --> "thingy.DB"
user.go --> "thingy.User"
page.go --> "thingy.Page"
// implements DB
mysqldb/db.go
mysqldb/user.go
mysqldb/page.go
This is useful if you intend the "thingy" to be reusable and have multiple different servers. e.g. this is the approach I used for
https://github.com/egonelbre/fedwiki, because the core server stays the same, but there are lots of different configurations that it can run.
Or...
user/mysql-userrepo/...
user/info.go
user/repo.go
page/mysql-pagerepo/... (package is named "pagerepo")
page/info.go
page/repo.go
pages/server.go
admin/server.go
admin/service.go
admin/page.go
home/page.go
main.go
If you intend it to contain lots of different functionalities and integrate them... (this I've used in another project, not public)
Here the main difference is caused by the difference in how important things are... in the 1st case, the important bit is how "User" and "Page" relate to each other, and the "server" becomes an implementation detail. In the second version the important pieces are the functionalities it has and "main.go" brings those pieces together.
There are tons of different ways of implementing those, but the main thing that controls the layout and where things go, is the "value" part and why it is "valued".
+ Egon