This could probably have been a blog post but I figured that I might try posting it here this time.
There was a thread recently that discussed examples of web applications. As far as I know, there is no preferred way of structuring your web application, although some variants might be more idiomatic than others. A couple of examples came up and I started checking them out to look for similarities. I believe that one of the strengths of Go is that you can choose whatever way that solves the particular problem you are having. Still though, it might be fun to see what people tend to go with
Starting out from scratch, your service will most likely fit into the main.go
. Handlers, middleware and all.
main.go
As your application starts exposing multiple endpoints, you might at some point want to extract your endpoints to separate *.go-files. Either you create a single handlers.go
or you have one file for each resource:
groups.go
main.go
users.go
Note that this will make go run main.go
fail and you might instead use the go build && ./app
approach.
Now, many (if not all) projects I have looked at prefer to move the resource files into a server
(or web
, or app
) directory.
main.go
server/
groups.go
users.go
At this point, I would like to point out some things that are common enough to consider general practice.
Persistence
At this point you might want to start persisting your posts, users or what you may have. Almost every application I have looked at will create a root-level package that contains your storage implementation.
database
, db
, store
, storage
.
Configuration
Applications that need additional configuration will have a root-level directory containing json, yaml, xml or even *.go files containing structs that are initialized from environment variables in the package func init()
.
configuration
, config
, conf
.
Templates
Templates will also be located at root-level in its own package.
templates
, tmpl
.
Things that are common enough to be mentioned are:
Utilities
Interestingly enough, utility
seems to be popular as it exists in many of the popular applications I have looked at.
util
, utils
Models
Some of the apps will also have the model
package containing their domain objects.
model
, models
Evolving further
So letās say we need a database, configuration as well as templates, our project will look something like this:
configuration/
database/
main.go
server/
groups.go
users.go
templates/
Now, some of the applications provide a command-line interface or similar applications. Letās create a cli
package at root-level.
cli/
main.go
configuration/
database/
main.go
server/
templates/
By keeping a main.go
in the root-level, to me this signals that there is a notion of a primary application. Is it our cli or the server? Some projects move the root-level main.go
into server
while others create a cmd/
directory containing the supporting applications.
cmd/
cli/
main.go
configuration/
database/
server/
main.go
templates/
or ā¦
cli/
main.go
configuration/
database/
server/
main.go
templates/
If we look closer at the server
package, several of the applications create a middleware.go
and/or router.go
to extract functionality from main.go
. You might even find apps that create separate packages within server/
.
cli/
main.go
configuration/
database/
server/
middleware/
router.go
main.go
templates/
Obviously, not all web applications I have looked at look the same but by normalizing package names and squinting a bit, there seems to be some common ways to structure web applications in Go.
If you would like to check out the web applications for yourself, these are some of the examples I have used when doing this post. Note that some of these are other permutations of the ones I have listed above.
- EmileVauge/traefik
- Unknwon/gowalker
- drone/drone
- fiorix/freegeoip
- gogits/gogs
- golang/blog
- golang/gddo
- kabukki/journey
- mattermost/platform
- jmoiron/monet
These are the ones I managed to find (as well as a few smaller applications that fit into some of these āarchetypesā.
Do you agree with my findings? Do you know of any other applications that wonāt fit into any of these examples? I would be happy to update this post based on your observations.