This starter kit is designed to get you up and running with a project structure optimal for developing RESTful services in Go. The kit promotes the best practices that follow the SOLID principles and encourage writing clear and idiomatic Go code.
The kit provides the following features right out of the box
- RESTful endpoints in the widely accepted format
- Standard CRUD operations of a database table
- JWT-based authentication
- Application configuration via environment variable and configuration file
- Structured logging with contextual information
- Panic handling and proper error response generation
- Automatic DB transaction handling
- Data validation
- Full test coverage
The kit uses the following Go packages which can be easily replaced with your own favorite ones since their usages are mostly localized and abstracted.
- Routing framework: ozzo-routing
- Database: ozzo-dbx
- Data validation: ozzo-validation
- Logging: logrus
- Configuration: viper
- Dependency management: dep
- Testing: testify
If this is your first time encountering Go, please follow the instructions to install Go on your computer. The kit requires Go 1.5 or above.
After installing Go, run the following commands to download and install this starter kit:
# install the starter kit
go get github.com/erikmswan/go-http-server
# install dep
$ curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
# fetch the dependent packages
cd $GOPATH/erikmswan/go-http-server
dep ensure
Next, create a PostgreSQL database named go_restful
and execute the SQL statements given in the file testdata/db.sql
.
The starter kit uses the following default database connection information:
- server address:
127.0.0.1
(local machine) - server port:
5432
- database name:
go_restful
- username:
postgres
- password:
postgres
If your connection is different from the above, you may modify the configuration file config/app.yaml
, or
define an environment variable named RESTFUL_DSN
like the following:
postgres://<username>:<password>@<server-address>:<server-port>/<db-name>
For more details about specifying a PostgreSQL DSN, please refer to the documentation.
Now you can build and run the application by running the following command under the
$GOPATH/erikmswan/go-http-server
directory:
go run server.go
or simply the following if you have the make
tool:
make
The application runs as an HTTP server at port 8080. It provides the following RESTful endpoints:
GET /ping
: a ping service mainly provided for health check purposePOST /v1/auth
: authenticate a userGET /v1/artists
: returns a paginated list of the artistsGET /v1/artists/:id
: returns the detailed information of an artistPOST /v1/artists
: creates a new artistPUT /v1/artists/:id
: updates an existing artistDELETE /v1/artists/:id
: deletes an artist
For example, if you access the URL http://localhost:8080/ping
in a browser, you should see the browser
displays something like OK v0.1#bc41dce
.
If you have cURL
or some API client tools (e.g. Postman), you may try the following more complex scenarios:
# authenticate the user via: POST /v1/auth
curl -X POST -H "Content-Type: application/json" -d '{"username": "demo", "password": "pass"}' http://localhost:8080/v1/auth
# should return a JWT token like: {"token":"...JWT token here..."}
# with the above JWT token, access the artist resources, such as: GET /v1/artists
curl -X GET -H "Authorization: Bearer ...JWT token here..." http://localhost:8080/v1/artists
# should return a list of artist records in the JSON format
In this section, we will describe the steps you may take to make use of this starter kit in a real project. You may jump to the Project Structure section if you mainly want to learn about the project structure and the recommended practices.
To use the starter kit as a starting point of a real project whose package name is something like
github.com/abc/xyz
, take the following steps:
- move the directory
$GOPATH/github.com/erikmswan/go-http-server
to$GOPATH/github.com/abc/xyz
- do a global replacement of the string
github.com/erikmswan/go-http-server
in all of project files with the stringgithub.com/abc/xyz
To implement the CRUD APIs of another database table (assuming it is named as album
),
you will need to develop the following files which are similar to the artist.go
file in each folder:
models/album.go
: contains the data structure representing a row in the new table.services/album.go
: contains the business logic that implements the CRUD operations.daos/album.go
: contains the DAO (Data Access Object) layer that interacts with the database table.apis/album.go
: contains the API layer that wires up the HTTP routes with the corresponding service APIs.
Then, wire them up by modifying the serveResources()
function in the server.go
file.
- If the API uses a request/response structure that is different from a database model,
define the request/response model(s) in the
models
package. - In the
services
package create a service type that should contain the main service logic for the API. If the service logic is very complex or there are multiple related APIs, you may create a package underservices
to host them. - If the API needs to interact with the database or other persistent storage, create
a DAO type in the
daos
package. Otherwise, the DAO type can be skipped. - In the
apis
package, define the HTTP route and the corresponding API handler. - Finally, modify the
serveResources()
function in theserver.go
file to wire up the new API.
This starter kit divides the whole project into four main packages:
models
: contains the data structures used for communication between different layers.services
: contains the main business logic of the application.daos
: contains the DAO (Data Access Object) layer that interacts with persistent storage.apis
: contains the API layer that wires up the HTTP routes with the corresponding service APIs.
Dependency inversion principle is followed to make these packages independent of each other and thus easier to test and maintain.
The rest of the packages in the kit are used globally:
app
: contains routing middlewares and application-level configurationserrors
: contains error representation and handlingutil
: contains utility code
The main entry of the application is in the server.go
file. It does the following work:
- load external configuration
- establish database connection
- instantiate components and inject dependencies
- start the HTTP server