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.
- 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 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/
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"}]}
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:
- getting-started
- effective_go
- gobyexample
- Golang-SQLite-Simple-Example
- design-patterns
- golang-using-gin
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 😂