Skip to main content

How to Create a Web Server in Go using Gin (Golang)

This article covers how to create a simple Web server in Go using the Gin framework.

These instructions were written for a Mac. But they should easily translate to instructions for Linux or Windows.

Step 1. Setup your development environment

This article assumes that you've already installed Go.  If not, see the setup instructions in my previous article.

Step 2. Create a new project folder

At the command line create and/or browse to a folder where you keep your projects:

  • Add a new project folder
  • On a Mac I do it like this:
mkdir go-server
cd go-server

Step 3: Initialize the Go project

On the command line, adjust this command for your git service and username:

 go mod init github.com/mitchallen/go-server

You should see a response similar to this:

go: creating new go.mod: module github.com/mitchallen/go-server

On a Mac you can verify the file was created doing this:

ls -ls
cat go.mod

You should see something like this:

module github.com/mitchallen/go-server
go 1.20

Step 4. Install the Gin framework

From the root of your project folder, run this command to install the Gin framework:

go get -u github.com/gin-gonic/gin

Step 5. Create a source file

Create an empty file to update in later steps:

On a Mac you can do it like this:

touch server.go

Step 6. Edit server.go

Using your favorite code editor, paste this code into server.go and save it:

/**
* Author: Mitch Allen
* File: server.go
*/

package main

import "github.com/gin-gonic/gin"

func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "Hello, world!",
})
})
// listen and serve on 0.0.0.0:8080
// on windows "localhost:8080"
// can be overriden with the PORT env var
r.Run()
}

This code creates a new Gin router instance using gin.Default(). It then sets up a route that responds to GET requests to the root path ("/") by returning a JSON response with a "message" key and the value "Hello, world!". Finally, it starts the web server and listens on port 8080.

As you will see in the next step, you can override the default port using an environment variable when you run the server.

Step 7. Run the server

In a command or terminal window do the following:

  • Change to the folder where your server.go file is if you aren't there already
  • Run this command:
PORT=8085 go run server.go

The command runs the server, but sets the PORT to 8085, overriding the default port.  This makes it easy to change ports if you have a conflict on your machine.

Step 8. Test the server

You can test the server in a browser, like Chrome that will return the JSON response.

{"message":"Hello, world!"}

If you have curl installed, you can also test it like this in a second terminal window:

curl http://localhost:8085/

Step 9. Creating Routes and Handling Requests

To create more complex routes and handle requests, you can use the r.GET, r.POST, r.PUT, and r.DELETE methods to set up routes for different HTTP methods. You can then add a function as the second argument to each method to handle the request.

For example, to create a route that responds to GET requests to "/users" and returns a JSON response with a list of users, you can add the following code above the r.Run() statement:

r.GET("/users", func(c *gin.Context) {
users := []string{"Alice", "Bob", "Charlie"}
c.JSON(200, gin.H{
"users": users,
})
})
  • Stop the server using Ctrl-C in the terminal window
  • Save server.go
  • Run the server again

To test from a second terminal window, run this curl command with the modified path:

curl http://localhost:8085/users

You should get a response like this:

{"users":["Alice","Bob","Charlie"]}

Step 10. Add a Post Request Handler

Similarly, to handle POST requests to "/users" and create a new user, we can add the following code:

r.POST("/users", func(c *gin.Context) {
var user struct {
Name string `json:"name"`
Email string `json:"email"`
}
if err := c.BindJSON(&user); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
// TODO: create user in database
c.JSON(201, gin.H{"message": "User created"})
})

This code defines a new struct called user that has Name and Email fields. You can then use c.BindJSON to parse the JSON request body and populate the user struct with the values. If there is an error parsing the JSON, return a 400 error response. Otherwise, create the user in the database (which we haven't implemented yet, because that's beyond the scope of this article), and return a 201 response with a "message" key.

Test it using this curl command:

 curl -X POST http://localhost:8085/users \
-H "Content-Type: application/json" \
-d '{"name":"John Doe","email":"[email protected]"}'

You should get a response like this:

{"message":"User created"}

Let's break down the command:

  • -X POST specifies that we want to perform a POST request
  • -H "Content-Type: application/json" sets the Content-Type header to application/json, indicating that we are sending JSON data in the request body
  • -d '{"name": "John Doe", "email": "[email protected]"}' specifies the data to be sent in the request body as a JSON payload
  • http://localhost:8085/users is the URL of the API endpoint we want to send the POST request to

After running this command, curl will send the POST request to http://localhost:8085/users with the JSON payload, and display the response from the server.

Conclusion

In this article, you learned how to:

  • Install the Gin Web server framework package for Go
  • Create and run a simple Web server in Go
  • Test the Web server using curl and a browser
  • Add an HTTP GET url handler
  • Add an HTTP POST url handler
  • How to test a POST handler using curl

References

  • Gin Web Framework - [1]
  • How to Create and Publish a Go Package (Golang) - [2]