Go Mini Projects — Build Real-World Go Applications from Scratch
DodaTech
Updated 2026-06-28
2 min read
In this tutorial, you will learn about Go Mini Projects. We cover key concepts, practical examples, and best practices to help you master this topic.
Go mini projects build a REST API server, CLI task manager, URL shortener, and file server applying slices, goroutines, HTTP, and JSON skills.
What You'll Learn
- REST API with Gin
- CLI task manager with cobra
- URL shortener with in-memory storage
- File server with middleware
Why It Matters
Projects reinforce learning. These projects mirror tools used at Docker, Kubernetes, and DodaTech.
Real-World Use
Internal REST APIs, DevOps automation tools, URL management services, static file serving.
REST API Server
package main
import (
"github.com/gin-gonic/gin"
)
type Task struct {
ID int `json:"id"`
Name string `json:"name" binding:"required"`
Done bool `json:"done"`
}
var tasks = []Task{}
var nextID = 1
func main() {
r := gin.Default()
r.GET("/tasks", func(c *gin.Context) {
c.JSON(200, tasks)
})
r.POST("/tasks", func(c *gin.Context) {
var task Task
if err := c.ShouldBindJSON(&task); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
task.ID = nextID
nextID++
tasks = append(tasks, task)
c.JSON(201, task)
})
r.DELETE("/tasks/:id", func(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
for i, t := range tasks {
if t.ID == id {
tasks = append(tasks[:i], tasks[i+1:]...)
c.JSON(200, gin.H{"deleted": id})
return
}
}
c.JSON(404, gin.H{"error": "not found"})
})
r.Run(":8080")
}
CLI Task Manager
package main
import "github.com/spf13/cobra"
var tasks []string
func main() {
root := &cobra.Command{Use: "task"}
root.AddCommand(&cobra.Command{
Use: "add [task]",
Run: func(cmd *cobra.Command, args []string) {
tasks = append(tasks, args[0])
fmt.Printf("Added: %s\n", args[0])
},
})
root.AddCommand(&cobra.Command{
Use: "list",
Run: func(cmd *cobra.Command, args []string) {
for i, t := range tasks {
fmt.Printf("%d. %s\n", i+1, t)
}
},
})
root.Execute()
}
URL Shortener
package main
import (
"crypto/rand"
"encoding/hex"
"net/http"
"sync"
)
type Store struct {
mu sync.RWMutex
urls map[string]string
}
func (s *Store) Shorten(original string) string {
s.mu.Lock()
defer s.mu.Unlock()
bytes := make([]byte, 3)
rand.Read(bytes)
key := hex.EncodeToString(bytes)
s.urls[key] = original
return key
}
func (s *Store) Resolve(key string) (string, bool) {
s.mu.RLock()
defer s.mu.RUnlock()
val, ok := s.urls[key]
return val, ok
}
File Server
func main() {
r := gin.Default()
r.Static("/static", "./public")
r.POST("/upload", func(c *gin.Context) {
file, _ := c.FormFile("file")
dst := filepath.Join("./uploads", file.Filename)
c.SaveUploadedFile(file, dst)
c.JSON(200, gin.H{"path": dst})
})
r.GET("/download/:name", func(c *gin.Context) {
name := c.Param("name")
c.File(filepath.Join("./uploads", name))
})
r.Run(":8080")
}
| Topic | Description | Link |
|---|---|---|
| Go Ecosystem | Community and tools | {{< ref "46-ecosystem" >}} |
| Go Web Frameworks | Gin, Echo, Fiber | {{< ref "40-web-frameworks" >}} |
| Ruby Mini Projects | Compare Ruby projects | Ruby |