Golang for Frontend developers | Beginner guide to Golang

Write a micro-service using Go and Go-Gin. A beginner guide to Golang, Introducing all the best practices and patterns.

Subscribe to my newsletter and never miss my upcoming articles

  • Are you a beginner and you want to start Golang but don't know how?
  • You have written express.js code and want to create micro-services using Golang?

Then this article is for you. This article will guide you step by step building block to build a scalable Golang project but in simple words.

Do I really need Golang?

Before going further you should ask this question to yourself and your teammates. Hope you are not migrating just for the sake that you want to try out something new. Golang is a new language but it is not that new. The first stable release was in 2009 the same as nodejs. Due to similarity or say javascript popularity, Nodejs become famous in a few years. React, Angular and other frontend framework help to make nodejs one of the popular language in the market.

Golang has a different type of fans. Just like any other stable language, it took time for Golang to become famous. Now it is a buzz word in all industries. However, Golang is not just a buzz word. It has defiantly the potential to become the first choice and it is happing already. Now Golang is the first choice for micro-service development.

The biggest reason for adaptation, This language is maintained by Google Team. And companies like Netflix, Google, Facebook are using it in production read more. Tools like Docker and kubernetes has been written on Golang. Due to its high performance, simplicity it is now goto go language.

You can ask me a question. If Golang is so good and it is in the market for such a long time why I am writing this blog now? The answer is simple, Recently one of my tool build on Golang went live in my Organization. So I want to share my experience.

Prerequisite

  • Golang[v1.16 and above]: You should have the latest version of Golang in your system. You can download and install Golang here.
  • Basic understanding of async programming
  • Basic understanding of functional programming
  • Linux/Unix: Since the examples and command will be written for the UNIX system. You can find similar command if you are working on a window system

Verify Golang

To verify, open and type the below command

go version

## output
go version go1.16.1 darwin/amd64

golang-introduction-hello-world.jpeg

Golang First program, "Hello, Golang ❤️"

Writing a Golang program is pretty simple. You can create a file with "package main".

touch main.go

Add below code in main.go

package main

import "fmt"

func main() {
    fmt.Println("Hello, Golang ❤️")
}

Running a Golang program: go run main.go

Explanation: Every Go Executable program required an entry file which should be defined in package main. And file should contain a main function.

Note: Golang is a compile and statically typed language, meaning you need to compile the program before running it. However, when you run an app using go run command. It creates a binary in the temp folder and executes it. In production, You should do this by own. You should not run an app using Go run.

Running app using the build command

## compile and build go app[You can give any name to executable using -o]
go build -o todo_app.exe main.go 

#### running a go app

./todo_app.exe

Clean up, Gitignore setup [optional]

## .gitignore

# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
# vendor/

manager.jpeg

Golang package manager, Start a new project

In version 1.11, Go introduce a new package manager similar to nodejs npm. This makes it easier to start a new project. To start a new project, You can create a folder and follow the below command.

mkdir todo_app
cd todo_app
go mod init github.com/deepakshrma/todo_app

Explanation: Here in the above code, You have created a folder. And just like node(npm) init. You have initialized a module with the name github.com/deepakshrma/todo_app. The module name can be anything. However, It is recommended to use your module hosting platform(here, in this case, github.com) followed by the username and app name.

Once you run the above command You can see a file will be created with the name go.mod. This will have all the dependencies and settings required by this app. You can read more on go.mod here. You can also watch EVERYTHING You SHOULD know about Go Modules , a nice video tutorial on youtube.

cat go.mod

## output
module github.com/deepakshrma/todo_app

go 1.16

Golang task manager, Build something new

Golang does not have an in-built task manager like the npm package. However, there is plenty of third-party modules available in the Golang world. I tried go-task module and I loved it. So we can use the same.

Create a Taskfile.yml in root folder

version: "3"

tasks:
  build-app:
    cmds:
      - go build -o todo_app.exe main.go
    silent: true

To use go-task, you have to install the binary. There are many ways you can install task binary. However, I recommend using the command go get -u github.com/go-task/task/v3/cmd/task. It will download go-task and create a binary in GOPATH. After that, you can use the task command globally.

Build using task

task build-app

Write your first micro-service

A micro-service(web service) can follow different architecture. For the demo, I will use the RESTfull API. You can find relevant doc for GRPC here.

Update main.go file

package main

// import net/http module

import (
    "fmt"
    "log"
    "net/http"
    "os"
)

// Route function to handle the request

func handleFunc(w http.ResponseWriter, req *http.Request) {
    fmt.Fprint(w, "Hello, Golang ❤️")
}

func main() {

    // Get the user provided port from ENV, if port is not defined user default port as 8080
    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
    }

    // Bind "/" as route to handleFunc
    http.HandleFunc("/", handleFunc)

    log.Printf("You app is running on http://localhost:%s", port)

    // Listen and Serve to localhost:port
    log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
}

Add a task to Tasklist.yml

version: "3"

tasks:
## rest of the tasks
  build-start:
    cmds:
      - go build -o todo_app.exe main.go && ./todo_app.exe

Run app: Once you add the task, You can build and run the app using the command task build-start. After that, you can open the URL to any browser http://localhost:8080 to see your first RESTfull API.

Implementing database repository

This article is just starting guideline. So, We will not use a real database to make the connection and save data. However to mimic the database let's create a repository. We will use an in-memory array/slice to contain data.

To create a simple database repository and add methods to insert and list Todo, Add the below code to the todo_app/repository/repository.go file.

package repository

import "time"

type Todo struct {
    Title       string    `json:"title"`
    Done        bool      `json:"done"`
    Description string    `json:"description"`
    CreatedAt   time.Time `json:"createdAt"`
}

type repository struct {
    db []Todo
}

var (
    r *repository
)

// This function will run one time when package is imported before anything else.
func init() {
    r = &repository{
        db: []Todo{},
    }
}

// Repository, Create public interface
type Repository interface {
    ListTodo() []Todo
    AddTodo(todo *Todo) Todo
}

// Repository, Get instance of singleton repository
func NewRepository() Repository {
    return r
}

func (r *repository) ListTodo() []Todo {
    return r.db
}

func (r *repository) AddTodo(todo *Todo) Todo {
    todo.CreatedAt = time.Now()
    r.db = append(r.db, *todo)
    return *todo
}

Here in the above code, We have exposed a singleton instance of Repository.

Let's tryout in main.go, we will remove this code later

 package main

import (
    "fmt"

    "github.com/deepakshrma/todo_app/repository"
)

func main() {
    r := repository.NewRepository()
    r.AddTodo(&repository.Todo{
        Title:       "Write a blog on golang",
        Description: "//TODO",
        Done:        false,
    })
    todos := r.ListTodo()
    for _, todo := range todos {
        fmt.Printf("%+v\n", todo)
    }
}

If you try the above code in the main function, You will see come output {Title: Write a blog on Golang Done:false Description://TODO CreatedAt:2021-03-27 14:16:00.03263 +0800 +08 m=+0.000465414}. We will update our router later.

Using a third-party module/package

We have created a simple route using http.HandleFunc. But managing multiple routes could be a challenge. And at the same time, we don't want to re-invent the wheel. Using a module in Golang is pretty simple. You can get any module from the Github repo. Let's use one of the best web framework modules gin-gonic.

To get a go module, you can use go get command or you can use go mod tidy after adding code.

// main.go

package main

import (
    "fmt"
    "log"
    "net/http"
    "os"

    "github.com/deepakshrma/todo_app/repository"
    "github.com/gin-gonic/gin"
)

var (
    r = repository.NewRepository()
)

func GetTodos(c *gin.Context) {
    c.JSON(http.StatusOK, gin.H{"data": r.ListTodo()})
}
func AddTodo(c *gin.Context) {
    var input repository.Todo
    if err := c.ShouldBindJSON(&input); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }
    r.AddTodo(&input)
    c.JSON(http.StatusOK, gin.H{"data": input})
}
func main() {
    // Get the user provided port from ENV, if port is not defined user default port as 8080
    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
    }
    router := gin.Default()
    v1 := router.Group("/v1")
    {
        v1.GET("/todos", GetTodos)
        v1.POST("/todos", AddTodo)
    }
    log.Fatal(router.Run(fmt.Sprintf(":%s", port)))
}

Run go mod tidy command and start the server

## get modules
go mod tidy

## build and start the server
 task build-start

Note: go mod tidy import module and same time clean up go.mod file by removing unused imports. It is a very handy command.

Explanation: Above code we have created a gin router with grouping them using API versioning. If you dot use Group, The default endpoint will be "/todos". But adding Group v1, Now all APIs need to add v1 to request resources.

Insert a todo and get the list using curl

You can use postman to insert and get data. However, for simplicity, I will use the curl command.

Insert data using endpoint

curl --header "Content-Type: application/json" \
  --request POST \
  --data '{"title":"Create Golang Tutorial","Description":"lets do it.."}' \
  http://localhost:8080/v1/todos
// result

{"data":{"title":"Create Golang Tutorial","done":false,"description":"lets do it..","createdAt":"2021-03-27T14:54:56.796403+08:00"}}

Fetch data using endpoint

curl http://localhost:8080/v1/todos
// result

{"data":[{"title":"Create Golang Tutorial","done":false,"description":"lets do it..","createdAt":"2021-03-27T14:54:56.796403+08:00"}]}

how to write a research paper conclusion (1)_1554820948.jpeg

Conclusions, Where to go from here

Finally, We have a working Micro Service. Definitely, This is not the perfect one. There are some other topics that need to be cover like Testing. However, It will give a kick start to write code in Golang. And thanks to the good community, You will find lots of nice document over the internet written by experts. Some article has been listed below.

References:

Source Code:

Quotes Of The Day:

Writing a micro-server is an art and to make good Art, Artist needs a good tool. Go is one of those tools. - Me 😂

No Comments Yet