DEV Community

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

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)