DEV Community

Cover image for 3 Exciting Go-lang Projects to Kickstart Your DevOps Journey
Pravesh Sudha
Pravesh Sudha Subscriber

Posted on • Edited on

3 Exciting Go-lang Projects to Kickstart Your DevOps Journey

๐Ÿ’ก Introduction

Welcome to the world of DevOps! ๐Ÿš€ Today, Iโ€™m back with another exciting blog to help you dive deeper into practical programming for DevOps tasks. In my previous blog, we explored 3 Python projects that laid the foundation for DevOps automation.

Now, letโ€™s switch gears and explore the power of Go-lang! This blog will guide you through building 3 Go-lang projects that are both practical and beginner-friendly:

  • A Monitor Disk Usage tool for tracking storage stats.
  • Hosting a resume website using an HTTP server.
  • A RESTful API program to manage DevOps tools.

So, grab your favorite code editor, and letโ€™s get started! ๐ŸŽ‰


๐Ÿ’ก Pre-Requisites

Before we dive into building these projects, letโ€™s make sure your environment is set up and ready to go. Hereโ€™s what you need:

1. Go (Golang)
Youโ€™ll need to have Go installed on your system. Follow these steps based on your operating system:

Windows

  • Download the latest Go installer from the official website.
  • Run the installer and follow the on-screen instructions.
  • Verify the installation by opening Command Prompt or PowerShell and typing:
go version
Enter fullscreen mode Exit fullscreen mode

Ubuntu

  • Open a terminal and run:
sudo apt update  
sudo apt install -y golang
Enter fullscreen mode Exit fullscreen mode
  • Verify the installation:
go version
Enter fullscreen mode Exit fullscreen mode

macOS

  • Use Homebrew to install Go. Run:
brew install go
Enter fullscreen mode Exit fullscreen mode
  • Verify the installation:
go version
Enter fullscreen mode Exit fullscreen mode

2. Basic Understanding of Go

While you donโ€™t need to be an expert, having a fundamental understanding of Go concepts like variables, functions, and structs will help you follow along smoothly. If youโ€™re new to Go, I recommend exploring the Go Tour for a quick introduction.

With these prerequisites met, youโ€™re all set to start building these awesome Go-lang projects! ๐Ÿš€


๐Ÿ’ก Monitor Disk Usage App

Letโ€™s kick off our journey with the first project โ€” a disk usage monitoring tool. This program will help you analyze disk usage for any specified directory on your system.

You can find the source code in my GitHub repository. Letโ€™s start by creating a file named disk_usage.go and adding the following code:

package main

import (
    "fmt"
    "os"
    "syscall"
)
func getDiskUsage(path string) {
    var stat syscall.Statfs_t
    err := syscall.Statfs(path, &stat)
    if err != nil {
        fmt.Println("Error Fetching Disk Usage:", err)
        return
    }
    total := stat.Blocks * uint64(stat.Bsize)
    free := stat.Bfree * uint64(stat.Bsize)
    used := total - free
    percentUsed := float64(used) / float64(total) * 100
    fmt.Printf("Disk usage of %s:\n", path)
    fmt.Printf("Total: %d GB\n", total/1e9)
    fmt.Printf("Used: %d GB (%.2f%%)\n", used/1e9, percentUsed)
    fmt.Printf("Free: %d GB\n", free/1e9)
}
func main() {
    path := "/"
    if len(os.Args) > 1 {
        path = os.Args[1]
    }
    _, err := os.Stat(path)
    if os.IsNotExist(err) {
        fmt.Printf("Error: '%s' Path doesn't exist.\n", path)
        return
    } else if err != nil {
        fmt.Printf("Error occurred while accessing path %s: %v \n", path, err)
        return
    }
    getDiskUsage(path)
}
Enter fullscreen mode Exit fullscreen mode

How the Program Works:

  • The program uses the syscall.Statfs function to fetch disk statistics, including the total, used, and free space.
  • It calculates the percentage of disk space used and formats the output in a user-friendly way.
  • Error handling is implemented to check if the provided path exists or if thereโ€™s an issue accessing it.

Running the Program
To run the program, use the following commands:

  • Check the disk usage of a specific directory:
go run disk_usage.go /path/to/directory
Enter fullscreen mode Exit fullscreen mode
  • If no path is specified, the program defaults to the root directory (/):
go run disk_usage.go
Enter fullscreen mode Exit fullscreen mode

Image description

Since I have a single partition, I will get the same result if I provide different paths.

This project demonstrates how Go can interact with your systemโ€™s underlying APIs, making it a great starting point for system monitoring tasks. ๐ŸŽ‰


๐Ÿ’ก HTTP Server Program: Hosting a Portfolio Website

The second project involves creating an HTTP server in Go that hosts a portfolio website. This project demonstrates how you can build and serve static websites while incorporating a health check endpoint for monitoring.

You can find the source code in my GitHub repository.

Steps to Build the HTTP Server

  • Create a file named http_server.go and add the following code:
package main
import (
    "fmt"
    "net/http"
)
func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("OK"))
}
func main() {
    fs := http.FileServer(http.Dir("./static"))
    http.Handle("/", fs)
    http.HandleFunc("/health", healthCheckHandler)
    port := "8090"
    fmt.Printf("Starting server on port %s....", port)
    err := http.ListenAndServe(":"+port, nil)
    if err != nil {
        fmt.Println("Error starting server:", err)
    }
}
Enter fullscreen mode Exit fullscreen mode

How It Works

  • Static File Server: The http.FileServer function serves files from the ./static directory.
  • Health Check Endpoint: A /health route is defined to provide a simple health check metric.
  • Server Setup: The server listens on port 8090 by default, and any errors during startup are logged.

Creating the Portfolio Website

  1. Structure: Inside the static folder, create:

    • index.html
    • style.css
    • A folder named images with a profile picture named profile.jpeg.
  2. Add the following content to your files:

index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Pravesh Sudha - Portfolio</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <header>
        <div class="container">
            <img src="images/profile.jpeg" alt="Pravesh Sudha" class="profile-picture">
            <h1>Pravesh Sudha</h1>
            <p class="subtitle">DevOps Engineer | Freelancer at Fiverr | Tech Blogger</p>
        </div>
    </header>
    <main>
        <div class="about">
            <h2>About Me</h2>
            <p>
                I am a passionate DevOps engineer with extensive experience in containerization, orchestration, and cloud computing. 
                I love contributing to open-source projects and writing beginner-friendly guides on Hashnode and Medium.
            </p>
        </div>
        <div class="links">
            <h2>Connect with Me</h2>
            <ul>
                <li><a href="https://fiverr.com/praveshsudha" target="_blank">Fiverr Profile</a></li>
                <li><a href="https://praveshstwt.hashnode.dev" target="_blank">Hashnode Blog</a></li>
                <li><a href="https://medium.com/@programmerpravesh" target="_blank">Medium Blog</a></li>
                <li><a href="https://gravatar.com/praveshsudha" target="_blank">Gravatar</a></li>
            </ul>
        </div>
    </main>
    <footer>
        <p>ยฉ 2024 Pravesh Sudha</p>
    </footer>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

style.css:

body {
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 0;
    line-height: 1.6;
    color: #333;
    background-color: #f9f9f9;
}

header {
    background: #4caf50;
    color: #fff;
    padding: 20px 0;
    text-align: center;
}
header .profile-picture {
    width: 150px;
    height: 150px;
    border-radius: 50%;
    margin-bottom: 15px;
}
header h1 {
    font-size: 2.5em;
    margin: 0;
}
header .subtitle {
    font-size: 1.2em;
    margin: 0;
}
main {
    padding: 20px;
    max-width: 800px;
    margin: 20px auto;
    background: #fff;
    border-radius: 8px;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
main .about,
main .links {
    margin-bottom: 20px;
}
main .links ul {
    list-style: none;
    padding: 0;
}
main .links li {
    margin: 10px 0;
}
main .links a {
    color: #4caf50;
    text-decoration: none;
    font-weight: bold;
}
main .links a:hover {
    text-decoration: underline;
}
footer {
    text-align: center;
    padding: 10px 0;
    background: #333;
    color: #fff;
}
Enter fullscreen mode Exit fullscreen mode

Running the Program

  • Start the HTTP server with the following command:
go run http_server.go
Enter fullscreen mode Exit fullscreen mode
  • Your portfolio website will now be available at: localhost:8090

Accessing the Health Check
To check the health of the server, visit:

localhost:8090/health
Enter fullscreen mode Exit fullscreen mode

Image description

This project showcases how to use Go-lang to create a functional web server for hosting static content, with additional monitoring through a health check endpoint. ๐ŸŽ‰


๐Ÿ’ก RESTful API Project: Managing DevOps Tools

In the final project of this blog, weโ€™ll create a RESTful API that allows you to manage a list of DevOps tools. This program demonstrates the use of Goโ€™s net/http package to handle RESTful routes and manage data.

The complete source code is available on my GitHub repository.

Building the RESTful API
Step 1: Main Program
Create a file named main.go and add the following code:

package main

import (
    "log"
    "net/http"
    "project/tools"
)
func main() {
    http.HandleFunc("/tools", tools.ListTools)
    http.HandleFunc("/tools/add", tools.AddTool)
    http.HandleFunc("/tools/details", tools.ToolDetails)
    port := "8090"
    log.Printf("Starting the server at port %v", port)
    err := http.ListenAndServe(":"+port, nil)
    if err != nil {
        log.Fatal("Error starting the server:", err)
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Data Handling
In the tools directory, create a file named data.go and add:

package tools

import "sync"
// Tool represents a DevOps tool.
type Tool struct {
    Name        string `json:"name"`
    Description string `json:"description"`
    Category    string `json:"category"`
}
var toolStore = []Tool{
    {"Docker", "A Platform to build, run and share containerized applications.", "Containerization"},
    {"Kubernetes", "An orchestration tool for managing containerized workloads.", "Orchestration"},
    {"Jenkins", "An open-source automation server for CI/CD.", "CI/CD"},
}
var mu sync.Mutex
Enter fullscreen mode Exit fullscreen mode

Step 3: Handlers
In the tools directory, create another file named handler.go and add:

package tools

import (
    "encoding/json"
    "net/http"
)
// ListTools handles GET requests to list all tools.
func ListTools(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodGet {
        http.Error(w, "Invalid Request Method", http.StatusMethodNotAllowed)
        return
    }
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(toolStore)
}
// AddTool handles POST requests to add a new tool.
func AddTool(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodPost {
        http.Error(w, "Invalid Method Type", http.StatusMethodNotAllowed)
        return
    }
    var newTool Tool
    if err := json.NewDecoder(r.Body).Decode(&newTool); err != nil {
        http.Error(w, "Invalid Request Body", http.StatusBadRequest)
        return
    }
    mu.Lock()
    toolStore = append(toolStore, newTool)
    mu.Unlock()
    w.WriteHeader(http.StatusCreated)
    json.NewEncoder(w).Encode(newTool)
}
// ToolDetails handles GET requests to fetch details of a specific tool.
func ToolDetails(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodGet {
        http.Error(w, "Invalid Method Type", http.StatusMethodNotAllowed)
        return
    }
    toolName := r.URL.Query().Get("name")
    if toolName == "" {
        http.Error(w, "Missing Tool Name", http.StatusBadRequest)
        return
    }
    mu.Lock()
    defer mu.Unlock()
    for _, tool := range toolStore {
        if tool.Name == toolName {
            w.Header().Set("Content-Type", "application/json")
            json.NewEncoder(w).Encode(tool)
            return
        }
    }
    http.Error(w, "Tool Not Found", http.StatusNotFound)
}
Enter fullscreen mode Exit fullscreen mode

Initializing the Module

Before running the program, initialize the Go module:

go mod init project
Enter fullscreen mode Exit fullscreen mode

This ensures the project can use the project/tools package.

Running the Program
Start the server by running:

go run main.go
Enter fullscreen mode Exit fullscreen mode

Testing the API

  1. List All Tools To fetch the list of tools, use:
curl localhost:8090/tools
Enter fullscreen mode Exit fullscreen mode

Image description

Output:

[
  {"name":"Docker","description":"A Platform to build, run and share Containerized applications.","category":"Containerization"},
  {"name":"Kubernetes","description":"An orchestration tool for managing containerized workloads.","category":"Orchestration"},
  {"name":"Jenkins","description":"An open-source automation server for CICD","category":"CI/CD"}
]
Enter fullscreen mode Exit fullscreen mode
  1. Add a New Tool To add a new tool, use:
curl -X POST -H "Content-Type: application/json" \
-d '{"name":"Prometheus","description":"A monitoring system and time-series database.","category":"Monitoring"}' \
http://localhost:8090/tools/add
Enter fullscreen mode Exit fullscreen mode

Image description

Output:

{"name":"Prometheus","description":"A monitoring system and time-series database.","category":"Monitoring"}
Enter fullscreen mode Exit fullscreen mode
  1. Fetch Tool Details To fetch details of a specific tool, use:
curl "http://localhost:8090/tools/details?name=Prometheus"
Enter fullscreen mode Exit fullscreen mode

Output:

{"name":"Prometheus","description":"A monitoring system and time-series database.","category":"Monitoring"}
Enter fullscreen mode Exit fullscreen mode

Image description


๐Ÿ’ก Conclusion

In this blog, weโ€™ve explored three practical Go projects that help you get hands-on experience with different aspects of software development. From monitoring disk usage to building a simple HTTP server to hosting a portfolio website, and finally, creating a RESTful API to manage DevOps tools, these projects provide a solid foundation for anyone looking to sharpen their Go programming skills.

  • The disk usage monitoring application introduced you to system calls and basic file handling in Go, giving you insight into how you can interact with a machineโ€™s file system.
  • The HTTP server project allowed you to learn how to serve static files and handle basic health-check endpoints, helping you get started with web development in Go.
  • The RESTful API project demonstrated how to structure an API, manage data with concurrency control, and make your application interactive through POST and GET requests.

Each of these projects is a building block that can be expanded upon to suit real-world applications. Whether you are interested in monitoring systems, developing web applications, or building APIs, Go provides the simplicity and power needed for efficient development.

๐Ÿš€ For more informative blog, Follow me on Hashnode, X(Twitter) and LinkedIn.

Till then, Happy Coding!!

Happy Learning! ๐ŸŽ‰

Top comments (0)