Codementor Events

How to Set Up a Project in Echo

Published Aug 24, 2018

Learn how to set up an Echo project and organize code in this tutorial by J. Ben Huson, the author of Echo Quick Start Guide.

This tutorial will walk you through the initial creation of an application to best showcase the Echo framework. You can find the source code for this sample project at https://github.com/PacktPublishing/Echo-Essentials/tree/master/chapter2. The following is a preliminary use-case diagram showing the interactions you’ll be creating to this project:

1.png

Regardless of the particulars of the project, code organization is paramount to the success of the project. When you develop a Go web application with Echo, it helps to start your project with a strong directory structure. A well-thought-out structure limits the number of issues with cyclical imports, and will allow you to create a clean in-project dependency tree.

The organization must also be intuitive for collaboration with others. Web frameworks, such as Django for Python, have a very opinionated organization, which typically follows the Model–View–Controller paradigm. The need to separate business logic cleanly is also important, as well as persistence logic and the protocol-specific logic, including request and response structures.
Use git with the following commands:

mkdir -p $GOPATH/src/github.com/PacktPublishing

git clone https://github.com/PacktPublishing/Echo-Essentials

Structure the repository as follows:

$GOPATH/src/github.com/PacktPublishing/Echo-Essentials/chapter2/
bindings/
cmd/
service/
handlers/
middlewares/
models/
renderings/
static/

The preceding structure is broken down intuitively, and allows for application growth. As you can see in the following internal dependency diagram, it shows a very clean import path for the previously defined packages:

2.png

A brief commentary showing the reasoning for the structure is as follows:
• bindings
• The bindings directory will hold all of the protocol-specific data bindings for the application, such as form submission, query string, and JSON representations of application input
• It is fairly common to see generic application data models used for request and response types, but it is the opinion of the author that this causes issues when a developer wishes to version API definitions
• cmd
• The cmd directory can be thought of as the "entrypoint" for the application. By separating the cmd/service package from the root package of the project, you can add a structure to allow for multiple applications in one project.
• For example, if you wanted to implement the scheduler portion of the application as a standalone daemon that needs to use modules defined within the same repository, you can do so by creating a new cmd/scheduler package to handle this case.
• Eventually, after a product is developed, it is often found that creating microservices is useful. With this cmd package, you can easily create different packages, which will become new executable services, and you can still use the existing codebase structure to support this task.
• handlers
• The handlers package is where you store all your Echo web application-handler code and business logic for the application
• middlewares
• The middlewares package is where you’ll store all your Echo web application middleware code and business logic that is applicable for more than one handler within the service
• Example middleware from the use-case diagram would be the "Verify Token" functionality, which will validate whether the requester is who they say they are.
• models
• Within an application, you’ll have application-specific data structures that you will need to persist to a database. The models package will house the application-specific types.
• The models package is separated from bindings and renderings, as you may wish to have both binding types and rendering types based on a common model. This structure will make this easier.
• renderings
• The renderings package will contain all the data structures and types that will be serialized back to the caller through the http.ResponseWriter
• static
• The static directory will contain all static assets and content that is required for the application. In some cases, you may want to render HTML templates to the caller. In other cases, you may need to serve JavaScript or images back to the caller. Within the Echo project, all the static content you’ll reference will live in this "package".

Implementing the project

The following code is located in the $GOPATH/src/github.com/PacktPublishing/Echo-Essentials/chapter2/cmd/service/main.go file:
package main

import (
"github.com/PacktPublishing/Echo-Essentials/chapter2/handlers"
"github.com/labstack/echo"
)

func main() {
// create a new echo instance
e := echo.New()
// Route / to handler function
e.GET("/health-check", handlers.HealthCheck)
// Authentication routes
e.POST("/login", handlers.Login)
e.POST("/logout", handlers.Logout)
// start the server, and log if it fails
e.Logger.Fatal(e.Start(":8080")) }

Within the preceding code block, a new Echo server is instantiated, and a route is added to the path /health-check, which will be routed to the handlers.HealthCheck function. The server is started on port 8080 on the final line of the main function. This code imports the handler module, which has a file called $GOPATH/src/github.com/PacktPublishing/Echo-Essentials/chapter2/handlers/health_check.go, as seen in the following code:

package handlers

import (
"net/http"

    "github.com/PacktPublishing/Echo-Essentials/plsding.me/renderings"
    "github.com/labstack/echo"

)

// HealthCheck - Health Check Handler
func HealthCheck(c echo.Context) error {
resp := renderings.HealthCheckResponse{
Message: "Everything is good!",
}
return c.JSON(http.StatusOK, resp)
}

The handlers package houses all of the API business logic in the form of Echo style handlers. As you may know, Go's net/http package defines a handler function signature as a function that takes in an http.ResponseWriter and a http.Request. The handler type in Echo is a function that takes in an Echo Context, and returns an error.

Within the Echo Context, you can have access to the request as well as the response writer if you want to access them directly. Echo also provides useful helper methods off of the Echo Context. For example, c.JSON in the preceding code takes the status parameter and an interface{}, and will render the provided interface{} as JSON before writing that result to the http.ResponseWriter for you!
You may also notice that the renderings package is being imported here. As mentioned previously, designate all response structures to belong to this rendering package for ease of application development. Within the renderings directory is a file called health_check.go, which contains the following:

package renderings

type HealthCheckResponse struct {
Message string json:"message"
}

This HealthCheckResponse structure contains one attribute called Message. It should be noted with this project layout structure that you can and should name all your related files similarly to keep the code structure as intuitive as possible. Within the handlers directory, there is a health_check.go file, which will handle all of the health check-related application logic. Similarly, there is a renderings health_check.go, which will store all the renderings related to the health check response structures.

Dependency management

One directory that hasn’t been mentioned so far is the vendor directory. The vendor directory in a Go project is a special directory. This is where dependency management for your project will be stored. The dep tool will be used for the purposes of this tutorial. In a nutshell, dep is a dependency management tool that will allow you to version pin your dependencies to a project.

It works by taking all the imported packages that were retrieved with go get or git commands directly in your $GOPATH and copies the relevant source code into this vendor directory within your project. The tool does so by reading your source code import statements and figuring out which packages you need. To get you started, you need to get the dep command with the following command:

go get -u github.com/golang/dep/cmd/dep

After you’ve installed the dep tool, you can initialize your project's vendor directory, as shown in the following code. When the dep tool initializes a project, it will take all the dependencies you have imported and put the code in the vendor directory:

dep init

It is highly recommended that some form of dependency management is used within Go projects. There is nothing worse than a project build failure related to the removal of a dependency from the internet, such as the left-pad issue with NPM. You can avoid this type of issue by committing the vendor directory directly into your repository, and versioning it with the rest of your code. There are drawbacks to this approach—namely, the size of pull and merge requests grow very large when there are significant changes to the dependencies of a project. It is the author's opinion, however, that these sorts of large dependency changes are indicative of possibly a larger workflow problem.

If you enjoyed this tutorial and want to learn more about the Echo framework, you can refer to Echo Quick Start Guide. The book creates a working example of a web application written with the Echo framework, and shows you enough of Echo to give context to bootstrap a high-performance web applications efficiently.

Discover and read more posts from PACKT
get started
post commentsBe the first to share your opinion
Show more replies