30 September 2026
From Hello World to Real-World Applications with Go
A journey from basic Go syntax to APIs, databases, testing, and deployment.
Ketika pertama kali belajar Go, mungkin kita memulainya dengan kode yang sangat sederhana:
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
Program tersebut berjalan.
Kita senang karena berhasil membuat program pertama.
Lalu kita belajar variable, function, struct, slice, interface, dan berbagai hal lainnya.
Sampai akhirnya muncul sebuah pertanyaan:
“Setelah belajar semua ini, sebenarnya aku bisa membuat apa?”
Menurutku, pertanyaan ini jauh lebih penting daripada sekadar menghafalkan syntax.
Karena belajar programming bukan hanya tentang bisa menulis kode.
Kita juga perlu belajar bagaimana mengubah kode menjadi sesuatu yang benar-benar bisa digunakan.
Dan untuk memahami itu, kita perlu keluar sedikit dari dunia Hello World.
Jangan Terlalu Lama Tinggal di Tutorial
Ada fase dalam belajar programming ketika kita merasa harus belajar semuanya terlebih dahulu.
Misalnya ketika belajar Go:
- harus memahami semua syntax
- harus memahami interface
- harus memahami goroutine
- harus memahami concurrency
- harus memahami framework
- harus memahami Docker
- harus memahami cloud
Baru setelah itu merasa siap membuat aplikasi.
Masalahnya, fase “siap” tersebut mungkin tidak pernah datang.
Karena semakin banyak kita belajar, semakin banyak pula hal baru yang kita temukan.
Menurutku, cara yang lebih masuk akal adalah:
Belajar sedikit
↓
Buat sesuatu
↓
Menemukan masalah
↓
Belajar untuk menyelesaikan masalah
↓
Buat lagi
Jadi kita tidak belajar semua hal terlebih dahulu.
Kita belajar karena project membutuhkannya.
Dari Hello World ke Todo App
Untuk melihat prosesnya, mari kita ambil project yang sangat sederhana:
Todo App.
Mungkin Todo terdengar terlalu sederhana.
Tapi justru karena sederhana, kita bisa melihat bagaimana sebuah aplikasi tumbuh.
Awalnya:
Hello World
Kemudian:
Go Program
Lalu:
HTTP Server
Kemudian:
REST API
Lalu:
Database
Kemudian:
Testing
Dan akhirnya:
Application
Satu project kecil bisa membawa kita melewati banyak konsep penting.
1. Mulai dari Program Go Sederhana
Kita mulai dengan membuat project:
mkdir todo-app
cd todo-app
go mod init todo-app
Kemudian buat main.go:
package main
import "fmt"
func main() {
fmt.Println("Todo App")
}
Saat dijalankan:
go run .
kita mendapatkan:
Todo App
Tidak ada yang istimewa.
Tapi ini adalah fondasinya.
Sebuah aplikasi besar juga dimulai dari program yang bisa dijalankan.
2. Mengubah Program Menjadi Server
Sekarang kita ingin program tersebut bisa menerima request.
Go sudah menyediakan package net/http, jadi kita tidak perlu langsung menggunakan framework.
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/health", health)
fmt.Println("Server running on :8080")
http.ListenAndServe(":8080", nil)
}
func health(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "OK")
}
Jalankan:
go run .
Kemudian buka:
http://localhost:8080/health
Sekarang kita mendapatkan:
OK
Hal kecil ini sebenarnya cukup penting.
Program kita sekarang sudah bisa:
- menerima HTTP request
- menjalankan function
- mengirim response
Kita sudah mulai masuk ke dunia backend.
3. Membuat Todo
Sekarang kita membutuhkan data.
Kita bisa membuat struct:
type Todo struct {
ID int `json:"id"`
Title string `json:"title"`
Completed bool `json:"completed"`
}
Untuk sementara, kita simpan Todo di memory:
var todos = []Todo{
{
ID: 1,
Title: "Belajar Go",
Completed: false,
},
}
Kemudian kita buat endpoint:
GET /todos
yang mengembalikan data tersebut dalam bentuk JSON.
func getTodos(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(todos)
}
Sekarang browser bisa mendapatkan:
[
{
"id": 1,
"title": "Belajar Go",
"completed": false
}
]
Kita sudah memiliki API sederhana.
4. Membuat Data Baru
Tidak cukup hanya membaca data.
Kita juga ingin membuat Todo.
Misalnya:
POST /todos
dengan request:
{
"title": "Belajar REST API"
}
Kemudian server membuat:
{
"id": 2,
"title": "Belajar REST API",
"completed": false
}
Di sini kita mulai belajar konsep yang sebenarnya sering digunakan dalam backend:
- HTTP method
- request body
- JSON
- response
- status code
- validation
Ternyata membuat endpoint sederhana saja sudah membawa kita ke banyak konsep.
5. Masalah Pertama: Data Hilang
Kemudian kita menemukan masalah.
Data Todo masih berada di memory.
Kalau server dihentikan:
Ctrl + C
kemudian dijalankan lagi:
go run .
Todo kita hilang.
Kenapa?
Karena kita belum menggunakan database.
Dan ini contoh yang menurutku menarik dalam belajar programming.
Kita tidak perlu belajar database hanya karena tutorial mengatakan:
“Sekarang waktunya belajar database.”
Kita belajar database karena aplikasi kita membutuhkannya.
6. Menambahkan SQLite
Untuk aplikasi sederhana, SQLite sudah cukup.
Kita bisa memiliki:
todo.db
yang menyimpan data Todo.
Sekarang alurnya berubah:
Request
↓
Go
↓
SQLite
↓
Response
Data tidak lagi hilang ketika server dimatikan.
Di sini kita mulai belajar:
- SQL
- table
- insert
- select
- update
- delete
- database connection
Dan Todo App yang tadinya hanya beberapa baris kode mulai terasa seperti aplikasi sungguhan.
7. Mulai Memisahkan Kode
Semakin banyak fitur yang kita tambahkan, semakin banyak pula kode yang kita miliki.
Kalau semuanya dimasukkan ke main.go, file tersebut akan cepat menjadi berantakan.
Maka kita mulai memisahkan tanggung jawab.
Misalnya:
backend/
├── main.go
└── internal/
└── todo/
├── handler.go
├── service.go
├── repository.go
└── model.go
Sekarang setiap bagian memiliki pekerjaan yang lebih jelas.
Handler
Mengurus HTTP.
Request
↓
Handler
Service
Mengurus business logic.
Handler
↓
Service
Repository
Mengurus database.
Service
↓
Repository
↓
SQLite
Akhirnya alurnya menjadi:
Client
↓
Handler
↓
Service
↓
Repository
↓
SQLite
Ini bukan berarti semua project Go harus memiliki struktur seperti ini.
Justru kita sebaiknya tidak membuat struktur tersebut hanya karena terlihat profesional.
Kita membuatnya ketika project mulai membutuhkannya.
8. Mulai Mengenal Interface
Di bagian ini kita bisa mulai menggunakan interface.
Misalnya:
type Repository interface {
Create(todo Todo) error
FindAll() ([]Todo, error)
}
Kemudian service:
type service struct {
repo Repository
}
Hal yang menarik adalah service tidak perlu mengetahui detail database.
Service hanya tahu bahwa repo menyediakan operasi yang dibutuhkan.
Misalnya:
Service:
"Repository, tolong buatkan Todo."
Repository:
"Siap."
Service:
"Repository, berikan semua Todo."
Repository:
"Siap."
Service tidak perlu tahu apakah repository menggunakan SQLite, PostgreSQL, atau database lainnya.
Di sinilah interface mulai terasa manfaatnya.
Bukan sekadar syntax yang harus dihafalkan.
9. Testing
Setelah aplikasi mulai memiliki beberapa bagian, kita mulai memiliki masalah baru.
Bagaimana kita tahu perubahan yang kita buat tidak merusak kode sebelumnya?
Jawabannya:
testing.
Misalnya kita ingin memastikan service berhasil membuat Todo.
Kita bisa menulis:
func TestCreateTodo(t *testing.T) {
// arrange
// act
// assert
}
Testing membuat kita bisa memeriksa perilaku program secara otomatis.
Tanpa testing, kita mungkin harus mencoba semuanya secara manual.
Dengan testing, kita bisa mengatakan:
“Kalau input-nya seperti ini, hasil yang kuharapkan harus seperti ini.”
Kemudian Go akan membantu memeriksanya.
10. Membuat Frontend Sederhana
Sampai sekarang kita sudah memiliki backend.
Tetapi backend saja belum terlalu nyaman digunakan oleh pengguna biasa.
Kita membutuhkan interface.
Untuk project belajar, kita bahkan tidak perlu framework frontend.
Cukup:
frontend/
├── index.html
├── style.css
└── app.js
HTML:
<h1>Todo App</h1>
<input id="title" placeholder="Todo..." />
<button id="add">
Add
</button>
<ul id="todos"></ul>
Kemudian JavaScript mengambil data dari Go API:
async function loadTodos() {
const response = await fetch(
"http://localhost:8080/todos"
);
const todos = await response.json();
console.log(todos);
}
loadTodos();
Sekarang kita memiliki dua bagian:
Frontend
↓
HTTP
↓
Go Backend
↓
SQLite
Dan ini sudah sangat mirip dengan aplikasi web yang sebenarnya.
11. Git Mengubah Cara Kita Bekerja
Ketika project mulai berkembang, kita juga perlu mengelola perubahan kode.
Kita mulai menggunakan Git.
git init
Kemudian:
git add .
git commit -m "initial todo app"
Setelah itu project bisa disimpan di GitHub.
Git bukan hanya tempat untuk menyimpan kode.
Menurutku, Git juga membantu kita melihat perjalanan sebuah project.
Misalnya:
Initial project
↓
Add API
↓
Add SQLite
↓
Add repository
↓
Add service
↓
Add tests
↓
Add frontend
Kita bisa melihat bagaimana project yang awalnya kosong perlahan tumbuh.
12. Deployment
Ada satu tahap terakhir yang membuat project terasa jauh lebih nyata.
Deployment.
Selama ini aplikasi berjalan di:
localhost
Artinya hanya komputer kita yang bisa mengaksesnya.
Deployment membuat aplikasi kita berjalan di server yang bisa diakses melalui internet.
Alurnya menjadi:
Browser
↓
Internet
↓
Server
↓
Go Application
↓
Database
Sekarang aplikasi yang kita buat tidak hanya hidup di laptop.
Orang lain bisa menggunakannya.
Dan menurutku, di sinilah ada perubahan kecil dalam cara kita melihat programming.
Kita tidak lagi sekadar menulis program.
Kita mulai membangun produk kecil.
Apa yang Sebenarnya Kita Pelajari?
Kalau dilihat sekilas, project kita hanya:
Todo App.
Tapi sebenarnya kita sudah menyentuh banyak hal.
Go
- struct
- function
- package
- interface
- error handling
Backend
- HTTP
- REST API
- JSON
- request
- response
- status code
Database
- SQL
- SQLite
- CRUD
- repository
Architecture
- handler
- service
- repository
- interface
Testing
- unit test
- mock
- assertion
Frontend
- HTML
- CSS
- JavaScript
fetch()
Workflow
- Git
- GitHub
- deployment
Dan semuanya dipelajari melalui satu project.
Jangan Mengejar Teknologi
Setelah mulai masuk dunia programming, kita akan melihat banyak teknologi.
Docker
Redis
PostgreSQL
Kafka
RabbitMQ
Kubernetes
GraphQL
gRPC
Microservices
Cloud
Melihat semua itu bisa membuat kita berpikir:
“Aku harus belajar semuanya.”
Padahal belum tentu.
Misalnya project kita belum memiliki masalah caching.
Kenapa harus langsung belajar Redis?
Kalau belum membutuhkan containerization.
Kenapa harus langsung belajar Docker?
Kalau aplikasinya masih sederhana.
Kenapa harus menggunakan microservices?
Kita tidak perlu menyelesaikan masalah yang belum kita miliki.
Lebih baik:
Project
↓
Masalah
↓
Cari solusi
↓
Belajar teknologi
↓
Implementasi
Daripada:
Belajar semua teknologi
↓
Bingung mau digunakan untuk apa
Dari “Belajar Go” Menjadi “Membangun dengan Go”
Menurutku ada perbedaan besar antara dua kalimat ini.
Aku sedang belajar Go.
dan:
Aku sedang membangun aplikasi menggunakan Go.
Kalimat pertama berfokus pada bahasa.
Kalimat kedua berfokus pada kemampuan.
Kita tetap perlu belajar syntax.
Kita tetap perlu memahami konsep.
Tetapi akhirnya pengetahuan tersebut harus digunakan untuk membuat sesuatu.
Karena programming bukan hanya tentang mengetahui bagaimana menulis:
func hello() {
fmt.Println("Hello")
}
Tetapi juga mengetahui bagaimana kode tersebut menjadi bagian dari sistem yang lebih besar.
Project Kecil Adalah Latihan yang Bagus
Kita tidak harus langsung membuat:
- social media
- e-commerce
- banking system
- streaming platform
- AI application
Project sederhana justru bisa menjadi latihan yang sangat bagus.
Misalnya:
Todo App
Notes App
URL Shortener
Expense Tracker
Student Cash App
Book Library
Yang penting adalah membawa project tersebut sampai selesai.
Bukan hanya:
Coding
tetapi:
Coding
↓
Database
↓
API
↓
Testing
↓
Git
↓
Deployment
Dari Satu Project ke Project Berikutnya
Setelah Todo selesai, kita bisa membuat project berikutnya.
Tidak perlu mengulang semuanya dengan cara yang sama.
Misalnya project kedua memiliki:
Authentication
Project ketiga:
File Upload
Project keempat:
Pagination
Project kelima:
External API
Project berikutnya:
Background Job
Sedikit demi sedikit, kita akan menemukan pola yang sama.
Awalnya mungkin terasa seperti banyak hal yang berbeda.
Lama-lama kita mulai melihat bahwa sebagian besar aplikasi memiliki pola yang berulang.
Request
↓
Validate
↓
Business Logic
↓
Database
↓
Response
Dan ketika pola tersebut mulai terasa familiar, kita tidak lagi selalu mulai dari nol.
Penutup
Saya pikir salah satu kesalahan ketika belajar programming adalah terlalu fokus pada pertanyaan:
“Apa yang harus saya pelajari selanjutnya?”
Kadang pertanyaan yang lebih berguna adalah:
“Apa yang bisa saya bangun dengan apa yang sudah saya tahu?”
Karena ketika kita mulai membangun, kita akan menemukan sendiri apa yang belum kita ketahui.
Kita akan menemukan error.
Kita akan menemukan database yang tidak bekerja.
Kita akan bingung dengan interface.
Kita akan salah membuat API.
Kita akan memperbaiki code.
Kita akan menjalankan test.
Kita akan melakukan commit.
Dan mungkin deployment pertama kita juga gagal.
Tapi justru dari situlah proses belajar sebenarnya terjadi.
Kita mulai dari:
Hello World
Kemudian:
Go
↓
HTTP
↓
API
↓
Database
↓
Architecture
↓
Testing
↓
Frontend
↓
Git
↓
Deployment
Pada akhirnya, tujuan belajar Go bukan hanya supaya kita bisa mengatakan:
“Aku tahu Go.”
Tetapi supaya suatu hari kita bisa mengatakan:
“Aku punya masalah, dan aku tahu bagaimana mulai membangunnya menjadi sebuah aplikasi.”
Dan mungkin, semuanya memang harus dimulai dari satu program kecil:
fmt.Println("Hello, World!")
Lalu satu langkah kecil setelahnya.
Dan satu langkah lagi.
Sampai tanpa sadar, Hello World yang dulu hanya mencetak satu kalimat sudah berubah menjadi sesuatu yang benar-benar bisa digunakan orang lain.