Dokumentasi ditelusuri 22 Oktober 2026
Belajar Go (Golang) dari Nol: Panduan Lengkap, 20 Contoh Kode, CLI, dan API

Ilustrasi ImageGen untuk panduan belajar Go/Golang. Bukan screenshot atau bukti benchmark. Salin perintah dari artikel atau folder kode, bukan dari gambar.
Ingin belajar Go setelah mengenal PHP, JavaScript, atau Python? Mulailah dari program kecil yang hasilnya bisa diperiksa: menampilkan teks, mengolah daftar barang, membaca berkas, lalu membuat API. Setelah alur dasar dipahami, barulah tambahkan goroutine, channel, dan pembatalan pekerjaan.
Panduan ini menyediakan 20 contoh kode dasar, tiga contoh yang sengaja gagal dikompilasi, proyek pencarian teks lewat terminal, serta API katalog dan perhitungan harga. Seluruh kode memakai pustaka standar. Anda tidak perlu memasang framework web, database, atau modul pihak ketiga untuk menjalankan latihan inti.
Contoh disiapkan untuk Go 1.27 atau lebih baru, dengan deklarasi go 1.27.0 pada setiap go.mod. Pilihan ini disengaja karena proyek memakai encoding/json/v2, yang dijelaskan dalam dokumentasi Go terbaru. Jangan menyalin manifest lalu mencoba menjalankan seluruh paket pada compiler lama tanpa meninjau kompatibilitasnya. Go 1.27 (diakses 2026/10), Release Notes; Go JSON v2 (diakses 2026/10), Overview.
Tujuan akhirnya adalah Anda dapat menjelaskan alur program, memeriksa kesalahan, menjalankan pengujian, dan menyelesaikan satu proyek kecil. Rencana belajar serta ide pengembangan merupakan saran editorial. Dokumentasi resmi diperiksa pada 22 Oktober 2026 melalui Parallel Search dan TinyFish; hasil eksekusi kode dicatat terpisah dalam paket.
Daftar isi panduan
1. Apa itu Go dan mengapa sering disebut Golang?
Go adalah bahasa pemrograman yang mendukung pengetikan kuat, garbage collection, dan pemrograman concurrent. Program disusun dari package. Nama bahasa yang dipakai dokumentasi resminya adalah Go; dalam artikel ini, kata Golang digunakan sebagai istilah pencarian pendamping. Go Specification (diakses 2026/10), Introduction; Go FAQ (diakses 2026/10), nama bahasa.
Alasan editorial kami merekomendasikannya sebagai salah satu jalur belajar backend adalah kesempatan membuat layanan HTTP dari komponen pustaka standar. net/http menyediakan implementasi klien dan server HTTP, sehingga pembaca dapat memahami request, response, header, dan handler sebelum menambah framework. Go HTTP (diakses 2026/10), Overview.
Jangan menganggap pemilihan bahasa otomatis menyelesaikan semua persoalan website. Panduan ini tidak menyusun peringkat gaji, popularitas, atau performa dibanding PHP dan Rust. Jika ingin menilai bahasa untuk proyek nyata, tulis kebutuhan terlebih dahulu, buat prototipe, dan periksa hasilnya dengan data serta lingkungan yang relevan.
Garbage collection membantu pengelolaan memori, tetapi penggunaan memori tetap perlu diperhatikan. Panduan resmi GC membahas pertukaran penggunaan CPU, memori, dan latensi. Karena itu, hindari kesimpulan bahwa aplikasi Go pasti ringan tanpa melihat implementasi dan beban kerjanya. Go GC Guide (diakses 2026/10), Introduction dan trade-offs.
Untuk siapa artikel ini?
Panduan ini ditujukan untuk pembaca yang dapat menggunakan editor teks dan terminal. Anda boleh mengikuti dengan Windows PowerShell, Linux, atau macOS. Jika belum pernah memprogram, perlambat bagian fungsi, percabangan, dan koleksi sebelum melanjutkan concurrency.
Saran kami: selesaikan contoh dasar, lanjutkan CLI, kemudian API. Jangan langsung menambahkan database, autentikasi, container, dan banyak layanan sekaligus. Satu alat kecil yang dapat Anda jalankan ulang lebih berguna sebagai latihan daripada banyak potongan kode yang belum dipahami.
2. Istilah dasar sebelum mulai
| Istilah | Makna dalam panduan |
|---|---|
| Package | Kumpulan file Go yang membentuk satu unit kode |
| Module | Kumpulan package dengan identitas dan konfigurasi dalam go.mod |
main |
Package/fungsi yang digunakan pada program executable |
| Slice | Tampilan atas bagian array yang dapat berbagi data dasar |
| Map | Koleksi pasangan kunci dan nilai |
| Struct | Tipe yang mengelompokkan beberapa field |
| Interface | Kontrak perilaku yang dinyatakan lewat method |
| Goroutine | Unit eksekusi ringan yang dikelola runtime Go |
| Channel | Sarana mengirim dan menerima nilai antargoroutine |
| Context | Pembawa deadline, sinyal pembatalan, dan nilai lingkup request |
| Handler | Komponen yang menerima request HTTP dan menulis respons |
| Table-driven test | Pola menyatakan banyak kasus uji dalam satu tabel data |
Istilah bahasa mengikuti Go Specification (diakses 2026/10); module mengikuti Go Modules (diakses 2026/10). Goroutine dan context dijelaskan pada Go Tour Concurrency dan Go Context, diakses 2026/10. Table-driven test adalah pola pengujian yang dibahas dalam Go Wiki (diakses 2026/10).
Anda tidak perlu menghafal istilah tersebut sekarang. Ketika menemui pesan error atau fungsi yang belum dikenal, kembali ke contoh yang relevan. Tujuan tabel ini membantu pembacaan, bukan menambah daftar hafalan sebelum menulis program pertama.
3. Memasang Go di Windows, Linux, dan macOS

Ilustrasi ImageGen: memasang alat pengembangan dan memeriksa terminal. Tampilan layar bersifat ilustratif.
Unduh installer atau arsip dari halaman resmi Go dan pilih sesuai sistem operasi serta arsitektur komputer. Dokumentasi instalasi menyediakan petunjuk untuk Windows, macOS, dan Linux. Hindari mengekstrak distribusi baru di atas pohon instalasi Go lama tanpa mengikuti prosedur resmi. Go Install (diakses 2026/10), Go installation.
Windows dengan PowerShell
Jalankan installer resmi yang sesuai, ikuti langkahnya, lalu tutup dan buka PowerShell kembali. Periksa apakah terminal sudah mengenali alat Go:
go version
go env GOOS GOARCH GOTOOLCHAIN
Hasil yang dicari adalah versi Go, sistem operasi target, arsitektur, dan pengaturan toolchain. Jika go tidak dikenali, periksa apakah instalasi selesai dan apakah terminal baru sudah dibuka. Jangan langsung memindahkan folder sistem atau mengubah banyak pengaturan PATH sekaligus.
Linux atau macOS
Ikuti tab sistem operasi pada halaman instalasi resmi. Setelah langkah instalasi dan PATH selesai, buka terminal baru lalu jalankan perintah pemeriksaan yang sama. Simpan hasil go version dalam catatan proyek agar mudah membandingkan lingkungan ketika terjadi masalah.
Tidak perlu memakai nomor patch yang persis sama dengan paket ini untuk memulai, tetapi gunakan cabang compiler yang memenuhi manifest dan tetap dipelihara. Rujukan kebijakan rilis tersedia di Go Release Policy (diakses 2026/10). Jangan menganggap proyek yang memakai pustaka standar tidak perlu pembaruan toolchain.
Editor dan kebiasaan awal
Gunakan editor yang sudah nyaman. Dukungan Go pada editor dapat membantu navigasi dan pemformatan, tetapi seluruh latihan tetap dapat dijalankan dari terminal. Ketika menyimpan perubahan, pastikan file yang diedit memang berada pada folder proyek yang sedang dijalankan.
Tanda tahap ini selesai adalah Anda dapat membangun program kecil. Melihat nomor versi merupakan pemeriksaan instalasi, sedangkan menjalankan contoh pertama memastikan rangkaian kerja edit, compile, dan eksekusi benar-benar tersambung.
4. Memahami module dan cara memakai contoh ZIP
Di dalam paket terdapat tiga module terpisah: kode/dasar, kode/cari-teks, dan kode/api-katalog. Jalankan perintah dari direktori module yang ingin dipakai. Folder terluar ZIP tidak memiliki satu go.mod gabungan, sehingga go test ./... dari folder terluar bukan alur yang dimaksud.
Manifest contoh dasar:
module example.com/tumbas/go-dasar
go 1.27.0
module memberi identitas module, sedangkan baris go menyatakan versi minimum Go yang dibutuhkan. Identitas example.com/tumbas/... adalah contoh untuk latihan lokal, bukan alamat repositori yang dijanjikan tersedia. Go Modules (diakses 2026/10), Module paths dan go directive.
Dari folder kode/dasar, gunakan:
go run ./cmd/01_halo
go run ./cmd/02_variabel
go test ./...
go build ./...
Setiap contoh mempunyai folder sendiri di bawah cmd, sehingga fungsi main tidak saling bertabrakan. Untuk memulai proyek terpisah, buat folder baru lalu gunakan go mod init dengan identitas module Anda sendiri. Perintah Go dijelaskan pada Go Command (diakses 2026/10), run, test, build, dan mod.

Diagram editorial: alat yang dipakai selama belajar. Panah bukan urutan wajib setiap kali mengubah kode.
Jangan menambahkan dependensi hanya karena tutorial lain menggunakannya. Pada tahap ini, sasaran Anda adalah memahami package, alur program, dan error. Setelah kebutuhan tertentu muncul, barulah nilai apakah pustaka pihak ketiga memang membantu.
5. Contoh 1–4: sintaks, variabel, fungsi, dan kontrol alur
Contoh 1. Halo Go
File kode/dasar/cmd/01_halo/main.go:
package main
import "fmt"
func main() { fmt.Println("Halo, Go!") }
Jalankan dari kode/dasar:
go run ./cmd/01_halo
Keluaran yang diharapkan:
Halo, Go!
package main dan fungsi main digunakan untuk program executable. Package fmt menyediakan keluaran terformat. Ubah teks yang dicetak dan jalankan ulang untuk memastikan Anda sedang mengedit sumber yang tepat. Go Getting Started (diakses 2026/10), Write some code; Go fmt (diakses 2026/10), Println.
Contoh 2. Variabel dan tipe data
package main
import "fmt"
func main() {
nama := "Buku"
stok := 3
stok += 2
var harga uint64 = 25_000
fmt.Printf("%s: stok %d, harga Rp%d\n", nama, stok, harga)
}
Jalankan dari kode/dasar:
go run ./cmd/02_variabel
Keluaran yang diharapkan:
Buku: stok 5, harga Rp25000
Deklarasi singkat := dipakai di dalam fungsi, sementara var dapat menyatakan tipe secara eksplisit. Dalam contoh ini, stok bertambah dan harga memakai uint64. Angka sengaja kecil agar perhatian tetap pada sintaks. Go Specification (diakses 2026/10), Variable declarations dan Short variable declarations.
Latihan: ubah stok awal, harga, dan nama produk, lalu prediksi hasil sebelum menjalankan program. Setelah itu, coba menempatkan teks pada variabel angka dan baca pesan compiler. Tujuannya memahami kontrak tipe, bukan sekadar menemukan cara membuat pesan error hilang.
Contoh 3. Fungsi dengan hasil
package main
import "fmt"
func total(harga, jumlah uint64) uint64 { return harga * jumlah }
func main() { fmt.Println("Total:", total(25_000, 2)) }
Jalankan dari kode/dasar:
go run ./cmd/03_fungsi
Keluaran yang diharapkan:
Total: 50000
Fungsi menyatakan tipe parameter serta hasilnya. Operasi perkalian latihan ini belum memiliki pemeriksaan overflow. Untuk pengembangan, tetapkan batas angka atau lakukan pemeriksaan sebelum mengalikan input yang belum dipercaya. Perilaku overflow integer dijelaskan pada Go Specification (diakses 2026/10), Integer overflow.
Latihan: jadikan fungsi mengembalikan hasil dan error ketika jumlah melebihi batas yang Anda tetapkan. Tuliskan dahulu apakah nol diperbolehkan dan berapa maksimum jumlahnya. Keputusan tersebut adalah aturan aplikasi, sehingga sebaiknya tidak dibiarkan tersirat dalam implementasi.
Contoh 4. Percabangan dengan switch
package main
import "fmt"
func main() {
for _, stok := range []int{0, 2, 8} {
var status string
switch {
case stok == 0:
status = "habis"
case stok <= 3:
status = "menipis"
default:
status = "tersedia"
}
fmt.Printf("%d: %s\n", stok, status)
}
}
Jalankan dari kode/dasar:
go run ./cmd/04_kontrol
Keluaran yang diharapkan:
0: habis
2: menipis
8: tersedia
Go menggunakan for untuk perulangan dan menyediakan if serta switch untuk percabangan. Pada contoh ini, switch tanpa ekspresi memilih kondisi yang sesuai. Kita mengabaikan indeks perulangan melalui _ karena yang dibutuhkan hanya nilai stok. Effective Go (diakses 2026/10), Control structures.
Latihan: buat versi dengan if dan else if yang menghasilkan keluaran sama. Bandingkan bentuk yang paling mudah Anda jelaskan. Tidak ada kebutuhan membuat kode sesingkat mungkin bila bentuk yang lebih jelas membantu Anda memeriksa aturan status.
6. Contoh 5–9: koleksi, struct, pointer, dan interface
Contoh 5. Slice dapat berbagi data
package main
import (
"fmt"
"slices"
)
func main() {
awal := []int{3, 7}
pinjam := awal
pinjam[0] = 9
salinan := slices.Clone(awal)
salinan[0] = 1
fmt.Println("Awal:", awal)
fmt.Println("Salinan:", salinan)
}
Jalankan dari kode/dasar:
go run ./cmd/05_slice
Keluaran yang diharapkan:
Awal: [9 7]
Salinan: [1 7]
Penyalinan nilai slice tidak otomatis menyalin semua elemen array dasarnya. Karena itu perubahan melalui pinjam terlihat pada awal. slices.Clone membuat salinan elemen, tetapi salinan tersebut bersifat dangkal: elemen berupa pointer atau slice dapat tetap merujuk data lain yang sama. Go Slices (diakses 2026/10), internals; Go slices (diakses 2026/10), Clone.
Latihan: ubah elemen kedua dan amati hasilnya. Tunda eksperimen dengan append sampai Anda memahami panjang, kapasitas, dan array dasar. Jangan memakai satu hasil eksperimen append sebagai aturan umum, karena penggunaan kembali array bergantung pada kapasitas yang tersedia.
Contoh 6. Map dan hasil yang diurutkan
package main
import (
"fmt"
"sort"
"strings"
)
func main() {
hitung := map[string]int{}
for _, kata := range strings.Fields("go aman go ringkas") {
hitung[kata]++
}
kunci := make([]string, 0, len(hitung))
for kata := range hitung {
kunci = append(kunci, kata)
}
sort.Strings(kunci)
for _, kata := range kunci {
fmt.Printf("%s: %d\n", kata, hitung[kata])
}
}
Jalankan dari kode/dasar:
go run ./cmd/06_map
Keluaran yang diharapkan:
aman: 1
go: 2
ringkas: 1
Map menyimpan pasangan kunci dan nilai. Urutan iterasinya tidak dijamin, sehingga contoh mengurutkan daftar kunci sebelum mencetak hasil. strings.Fields memecah input berdasarkan whitespace. Go Maps (diakses 2026/10), Iteration order; Go strings (diakses 2026/10), Fields.
Penghitung ini belum menyamakan huruf besar atau membuang tanda baca. Itu batas desain latihan, bukan kesalahan pustaka. Jika ingin menganalisis dokumen, tetapkan apakah “Go”, “go”, dan “go.” dihitung sebagai token yang sama sebelum menambahkan normalisasi.
Contoh 7. Struct untuk data produk
package main
import "fmt"
type Produk struct {
Nama string
Harga uint64
}
func main() {
p := Produk{Nama: "Buku Go", Harga: 75_000}
fmt.Printf("%s: Rp%d\n", p.Nama, p.Harga)
}
Jalankan dari kode/dasar:
go run ./cmd/07_struct
Keluaran yang diharapkan:
Buku Go: Rp75000
Struct mengelompokkan field dalam satu tipe. Pada latihan, nama dan harga ditempatkan dalam Produk. Field dengan nama berawalan huruf besar diekspor dari package, sedangkan field lain tidak. Effective Go (diakses 2026/10), Names dan Data.
Latihan: tambahkan stok dan buat dua produk berbeda. Tentukan apakah harga memakai satuan rupiah utuh atau satuan terkecil lain. Untuk aplikasi pembayaran, representasi nominal harus mengikuti mata uang dan kebijakan pembulatan yang dirancang, bukan sekadar meniru tipe dari tutorial.
Contoh 8. Pointer untuk memperbarui nilai
package main
import "fmt"
func tambah(stok *int) { *stok += 1 }
func main() {
stok := 3
tambah(&stok)
fmt.Println("Stok:", stok)
}
Jalankan dari kode/dasar:
go run ./cmd/08_pointer
Keluaran yang diharapkan:
Stok: 4
&stok mengambil alamat variabel dan *stok mengakses nilai yang ditunjuk pointer. Fungsi dapat memperbarui nilai pemanggil melalui pointer tersebut. Go Specification (diakses 2026/10), Address operators.
Pointer di contoh ini diasumsikan tidak nil. Jika fungsi nantinya dipanggil dari jalur yang lebih luas, tetapkan kontraknya: apakah nil ditolak, diperiksa, atau tidak dapat muncul karena desain. Jangan menambahkan pointer pada setiap parameter tanpa kebutuhan perubahan atau pembagian data yang jelas.
Contoh 9. Method dan interface
package main
import "fmt"
type Ringkas interface{ Ringkasan() string }
type Artikel struct{ Judul string }
func (a Artikel) Ringkasan() string { return "Artikel: " + a.Judul }
func cetak(r Ringkas) { fmt.Println(r.Ringkasan()) }
func main() { cetak(Artikel{Judul: "Belajar Go"}) }
Jalankan dari kode/dasar:
go run ./cmd/09_interface
Keluaran yang diharapkan:
Artikel: Belajar Go
Tipe memenuhi interface ketika method set yang dibutuhkan tersedia; tidak ada deklarasi implements pada contoh Go ini. Fungsi cetak memerlukan perilaku Ringkasan, bukan susunan field tertentu. Effective Go (diakses 2026/10), Interfaces and other types.
Latihan: buat tipe lain yang juga memiliki Ringkasan() string, lalu teruskan ke fungsi yang sama. Setelah itu, pertimbangkan apakah kedua tipe memang digunakan melalui perilaku bersama. Hindari membuat banyak interface sebelum ada pemakai yang jelas; mulailah dari kebutuhan fungsi yang menerima nilainya.
7. Contoh 10–15: error, Unicode, JSON, defer, file, dan generic
Contoh 10. Mengembalikan dan membungkus error
package main
import (
"errors"
"fmt"
"strconv"
)
var ErrNol = errors.New("jumlah harus lebih dari nol")
func baca(teks string) (uint64, error) {
n, err := strconv.ParseUint(teks, 10, 64)
if err != nil {
return 0, fmt.Errorf("jumlah tidak valid: %w", err)
}
if n == 0 {
return 0, ErrNol
}
return n, nil
}
func main() {
n, err := baca("0")
if errors.Is(err, ErrNol) {
fmt.Println("Gagal: jumlah nol")
return
}
if err != nil {
fmt.Println("Gagal:", err)
return
}
fmt.Println("Jumlah:", n)
}
Jalankan dari kode/dasar:
go run ./cmd/10_error
Keluaran yang diharapkan:
Gagal: jumlah nol
Go dapat mengembalikan nilai dan error dari satu fungsi. %w membungkus error, sedangkan errors.Is memeriksa apakah error cocok dalam rantai pembungkusan. Memeriksa pesan error mentah sebagai satu-satunya kontrak akan menyulitkan perubahan teks. Go errors (diakses 2026/10), Overview dan Is.
Latihan: coba input “dua”, nol, dan dua. Bedakan kesalahan bentuk angka dari pelanggaran aturan jumlah. Jika menampilkan pesan kepada pengguna, pilih informasi yang membantu tindakan berikutnya tanpa mengeluarkan rincian internal yang tidak diperlukan.
Contoh 11. Byte dan rune pada teks
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
teks := "café"
fmt.Println("Byte:", len(teks))
fmt.Println("Rune:", utf8.RuneCountInString(teks))
fmt.Println("UTF-8 valid:", utf8.ValidString(teks))
}
Jalankan dari kode/dasar:
go run ./cmd/11_unicode
Keluaran yang diharapkan:
Byte: 5
Rune: 4
UTF-8 valid: true
String Go berisi byte dan tidak wajib merupakan UTF-8 valid. len menghitung byte, sedangkan fungsi utf8.RuneCountInString menghitung rune menurut aturan decoding UTF-8. Rune tidak selalu sama dengan satu karakter yang tampak bagi pembaca. Go Strings Blog (diakses 2026/10), Bytes, runes, dan characters; Go UTF8 (diakses 2026/10).
Latihan: ganti input dengan emoji dan teks yang memakai tanda gabung. Catat jumlah byte dan rune. Jika membatasi judul atau nama, tentukan apakah batasnya berbasis byte, rune, atau grapheme; jangan menganggap ketiganya selalu sama.
Contoh 12. JSON dengan encoding/json/v2
package main
import (
"encoding/json/v2"
"fmt"
)
type Input struct {
Nama string `json:"nama"`
}
func main() {
var input Input
data := []byte(`{"nama":"Buku"}`)
if err := json.Unmarshal(data, &input, json.RejectUnknownMembers(true)); err != nil {
fmt.Println("JSON tidak valid")
return
}
hasil, err := json.Marshal(input)
if err != nil {
fmt.Println("Gagal mengubah JSON")
return
}
fmt.Println(string(hasil))
}
Jalankan dari kode/dasar:
go run ./cmd/12_json
Keluaran yang diharapkan:
{"nama":"Buku"}
Paket JSON v2 menyediakan Marshal dan Unmarshal. Opsi RejectUnknownMembers(true) menolak nama field yang tidak sesuai struct. V2 juga secara default menolak nama anggota objek yang duplikat dan UTF-8 tidak valid. Ini berbeda dari sejumlah perilaku kompatibilitas paket JSON v1. Go JSON v2 (diakses 2026/10), Overview dan Security Considerations.
Contoh sengaja menargetkan Go 1.27. Jangan mengubah import ke encoding/json tanpa memeriksa perbedaan API dan hasilnya. Untuk belajar, tambahkan field asing ke input lalu amati penolakan. Dalam proyek API, kita juga akan memeriksa aturan bisnis setelah JSON berhasil dibaca.
Contoh 13. Defer dan urutan pekerjaan
package main
import "fmt"
func main() {
defer fmt.Println("Selesai")
fmt.Println("Mulai")
fmt.Println("Proses")
}
Jalankan dari kode/dasar:
go run ./cmd/13_defer
Keluaran yang diharapkan:
Mulai
Proses
Selesai
defer menunda pemanggilan hingga fungsi sekitarnya kembali. Ia sering dipakai untuk pembersihan resource setelah keberhasilan pembukaan. Argumen panggilannya dievaluasi saat statement defer dijalankan. Go Defer Blog (diakses 2026/10), Defer.
Jangan berasumsi semua defer akan dijalankan ketika memanggil os.Exit: fungsi itu menghentikan proses dan tidak menjalankan deferred calls. Karena itu proyek CLI mengembalikan exit code dari fungsi run, lalu memanggil os.Exit setelah fungsi tersebut selesai. Go os (diakses 2026/10), Exit.
Contoh 14. Membaca berkas lokal
package main
import (
"fmt"
"os"
"strings"
)
func main() {
data, err := os.ReadFile("data/contoh.txt")
if err != nil {
fmt.Fprintln(os.Stderr, "Gagal membaca:", err)
os.Exit(1)
}
baris := strings.Split(strings.TrimSpace(string(data)), "\n")
fmt.Println("Baris:", len(baris))
}
Jalankan dari kode/dasar:
go run ./cmd/14_file
Keluaran yang diharapkan:
Baris: 3
Jalankan contoh dari kode/dasar agar path data/contoh.txt sesuai direktori kerja. os.ReadFile membaca seluruh isi berkas dan mengembalikan data serta error. Go os (diakses 2026/10), ReadFile.
Penghitungan baris di sini sengaja sederhana untuk fixture tiga baris. Ia bukan pengurai semua format dokumen, dan bukan contoh streaming untuk berkas besar. Proyek CLI berikutnya menetapkan batas ukuran serta memakai Scanner agar perilaku baris dapat dipelajari lebih jelas.
Contoh 15. Generic untuk beberapa tipe
package main
import "fmt"
type Angka interface{ ~int | ~int64 }
func jumlah[T Angka](data []T) T {
var total T
for _, n := range data {
total += n
}
return total
}
func main() {
fmt.Println("int:", jumlah([]int{1, 2, 3}))
fmt.Println("int64:", jumlah([]int64{10, 20}))
}
Jalankan dari kode/dasar:
go run ./cmd/15_generic
Keluaran yang diharapkan:
int: 6
int64: 30
Generic menggunakan parameter tipe dan constraint. Tanda ~ di constraint memperbolehkan tipe dengan underlying type yang sesuai. Fungsi latihan menjumlahkan slice dari keluarga tipe angka yang dibatasi sendiri. Go Generics Tutorial (diakses 2026/10), Type constraints.
Latihan: buat tipe bernama yang underlying type-nya int64, lalu gunakan pada fungsi. Ingat bahwa generic tidak otomatis menambahkan pemeriksaan overflow. Jika kebutuhan hanya satu tipe sederhana, Anda tidak wajib mengubahnya menjadi generic agar terlihat lebih canggih.
8. Contoh 16–20: concurrency, context, HTTP, dan test

Ilustrasi ImageGen sebagai metafora pembagian pekerjaan. Bukan bukti bahwa program lebih cepat.
Contoh 16. Goroutine dan WaitGroup
package main
import (
"fmt"
"sort"
"sync"
)
func main() {
hasil := make(chan string, 2)
var wg sync.WaitGroup
for _, nama := range []string{"B", "A"} {
wg.Add(1)
go func(n string) {
defer wg.Done()
hasil <- "Tugas " + n
}(nama)
}
wg.Wait()
close(hasil)
daftar := make([]string, 0, 2)
for h := range hasil {
daftar = append(daftar, h)
}
sort.Strings(daftar)
for _, h := range daftar {
fmt.Println(h)
}
}
Jalankan dari kode/dasar:
go run ./cmd/16_goroutine
Keluaran yang diharapkan:
Tugas A
Tugas B
go memulai goroutine baru. WaitGroup dipakai untuk menunggu pekerjaan yang dicatat selesai. Contoh mengurutkan hasil sebelum mencetak karena urutan penyelesaian goroutine bukan kontrak yang dijanjikan. Go Tour Goroutines (diakses 2026/10); Go sync (diakses 2026/10), WaitGroup.
Perhatikan kapasitas channel dua: contoh menunggu dua produsen selesai sebelum membaca hasil. Jika Anda mengubahnya menjadi channel tanpa buffer dan tetap menunggu sebelum menerima, program dapat macet. Jangan mengubah kapasitas atau urutan menunggu tanpa memikirkan siapa yang dapat melanjutkan eksekusi.
Contoh 17. Channel dan penutupan aliran
package main
import "fmt"
func produksi(c chan<- int) {
defer close(c)
c <- 3
c <- 4
}
func main() {
c := make(chan int)
go produksi(c)
total := 0
for nilai := range c {
total += nilai
}
fmt.Println("Total:", total)
}
Jalankan dari kode/dasar:
go run ./cmd/17_channel
Keluaran yang diharapkan:
Total: 7
Channel tanpa buffer menyelaraskan pengirim dan penerima. Perulangan range atas channel berakhir setelah channel ditutup dan nilainya habis diterima. Pada desain contoh, produsen yang mengetahui kapan pengiriman selesai menutup channel. Go Tour Channels (diakses 2026/10); Go Tour Range and Close (diakses 2026/10).
Jangan menutup channel hanya karena satu penerima sudah tidak membutuhkan data jika produsen masih mengirim. Untuk latihan lanjutan, pikirkan pembatalan dan kepemilikan penutupan sejak awal. Gambar berikut memperlihatkan konsep aliran nilai, bukan pemetaan thread sistem operasi.

Diagram editorial: aliran contoh 17. Penerima menjumlahkan nilai tiga dan empat setelah diterima.
Contoh 18. Context dan pembatalan
package main
import (
"context"
"fmt"
)
func pekerjaan(ctx context.Context) error {
select {
case <-ctx.Done():
return ctx.Err()
default:
return nil
}
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
cancel()
fmt.Println("Status:", pekerjaan(ctx))
}
Jalankan dari kode/dasar:
go run ./cmd/18_context
Keluaran yang diharapkan:
Status: context canceled
Context membawa sinyal pembatalan dan deadline. Kode yang menerima context harus memeriksa atau meneruskannya ke operasi yang mendukung pembatalan; context tidak menghentikan sembarang pekerjaan secara paksa. Go Context (diakses 2026/10), Overview.
Contoh membatalkan sebelum memanggil pekerjaan agar hasilnya deterministik. Untuk proyek sebenarnya, tetapkan apa yang perlu dibersihkan saat pembatalan dan berapa lama operasi boleh menunggu. Jangan menyimpan context sebagai tempat umum menaruh seluruh konfigurasi aplikasi.
Contoh 19. HTTP client lokal dengan timeout
package main
import (
"fmt"
"io"
"net/http"
"net/http/httptest"
"time"
)
func main() {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Halo API")
}))
defer server.Close()
client := &http.Client{Timeout: 2 * time.Second}
resp, err := client.Get(server.URL)
if err != nil {
fmt.Println("Gagal HTTP")
return
}
defer resp.Body.Close()
body, err := io.ReadAll(io.LimitReader(resp.Body, 1024))
if err != nil {
fmt.Println("Gagal membaca")
return
}
fmt.Printf("%d: %s\n", resp.StatusCode, body)
}
Jalankan dari kode/dasar:
go run ./cmd/19_httpclient
Keluaran yang diharapkan:
200: Halo API
Contoh memakai server lokal dari httptest, sehingga tidak bergantung pada website eksternal. Client diberi timeout dan body ditutup sesudah selesai. LimitReader membatasi pembacaan tetapi tidak melaporkan kelebihan ukuran dengan sendirinya. Go HTTP (diakses 2026/10), Client dan Response Body; Go httptest (diakses 2026/10), NewServer; Go io (diakses 2026/10), LimitReader.
Saat mengembangkan client sungguhan, periksa status HTTP, batas body, dan format respons sebelum menggunakannya. Jangan menganggap error transport nil berarti layanan telah menerima permintaan secara bisnis. Respons 400 atau 500 tetap memerlukan penanganan sesuai kontrak layanan.
Contoh 20. Validasi dan table-driven test
package main
import (
"fmt"
"strings"
"unicode/utf8"
)
func namaValid(nama string) bool {
return utf8.ValidString(nama) && strings.TrimSpace(nama) != "" && utf8.RuneCountInString(nama) <= 40
}
func main() { fmt.Println("Valid:", namaValid("Buku")) }
Jalankan dari kode/dasar:
go run ./cmd/20_test
Keluaran yang diharapkan:
Valid: true
File test terpisah:
package main
import (
"strings"
"testing"
)
func TestNamaValid(t *testing.T) {
for _, tc := range []struct {
nama string
input string
ingin bool
}{
{"normal", "Buku", true},
{"kosong", "", false},
{"spasi", " ", false},
{"batas", strings.Repeat("a", 40), true},
{"panjang", strings.Repeat("a", 41), false},
{"utf8_invalid", string([]byte{0xff}), false},
} {
t.Run(tc.nama, func(t *testing.T) {
if dapat := namaValid(tc.input); dapat != tc.ingin {
t.Fatalf("dapat %v, ingin %v", dapat, tc.ingin)
}
})
}
}
go test -v ./cmd/20_test
Go mengenali fungsi test dalam file _test.go, dan t.Run membuat subtest. Tabel kasus membantu memeriksa beberapa kondisi dengan susunan yang seragam. Go testing (diakses 2026/10), Overview dan T.Run; Go TableDrivenTests (diakses 2026/10).
Tambahkan kasus sendiri sebelum mengubah aturan nama. Jika batas berubah dari empat puluh menjadi enam puluh rune, perbarui alasan bisnis dan kasus batasnya. Hindari mengganti assertion hanya agar test kembali lulus tanpa mengetahui perilaku yang ingin dijaga.
9. Membaca tiga kesalahan kompilasi yang disengaja
File contoh yang salah ditempatkan pada kode/dasar/testdata/gagal. Direktori testdata diabaikan dalam pencocokan package biasa oleh alat Go, sehingga contoh tersebut tidak merusak go test ./.... Go Command (diakses 2026/10), package lists.
Variabel lokal tidak dipakai
package main
func main() { angka := 10 }
go run testdata/gagal/01_tidak_dipakai.go
Compiler diharapkan menolak deklarasi lokal yang tidak digunakan. Perbaikannya bisa memakai nilai untuk tujuan yang nyata atau menghapus deklarasinya. Menambahkan _ = angka hanya masuk akal jika memang sedang menjelaskan eksperimen tertentu, bukan kebiasaan menutupi kode yang tidak diperlukan.
Nilai dengan tipe salah
package main
func main() { var angka int = "sepuluh"; _ = angka }
go run testdata/gagal/02_tipe_salah.go
Pesan yang dicari adalah ketidakcocokan tipe. Tentukan apakah input seharusnya tetap teks atau dikonversi menjadi angka melalui fungsi parsing yang dapat gagal. Konversi sebaiknya mengikuti makna data, bukan sekadar membuat assignment diterima compiler.
Fungsi tanpa hasil yang diwajibkan
package main
func hasil() int {}
func main() { _ = hasil() }
go run testdata/gagal/03_tanpa_return.go
Fungsi menyatakan hasil int tetapi tidak mengembalikannya. Tentukan hasil yang seharusnya atau ubah kontrak fungsi bila hasil memang tidak diperlukan. Detail aturan fungsi dan deklarasi tersedia dalam Go Specification (diakses 2026/10), Function declarations dan Declarations.
10. Proyek CLI: mencari teks dengan nomor baris

Ilustrasi ImageGen: alat bantu pencarian teks. Program contoh tidak mengubah berkas sumber.
Proyek cari-teks menggabungkan argumen terminal, io.Reader, pembatasan pembacaan, validasi UTF-8, dan penanganan error. Pencarian memakai substring yang peka huruf besar. Batas input dua MiB ditetapkan sebagai aturan latihan agar pemakaian memori dapat dibatasi.
Manifest dan struktur
module example.com/tumbas/cari-teks-go
go 1.27.0
cmd/cari-teks menyediakan program terminal, sedangkan internal/cari menyimpan logikanya. Folder fixtures berisi berkas contoh. Susunan ini dipilih agar fungsi pencarian bisa diuji tanpa selalu membuka proses executable.
Kode pencarian lengkap
package cari
import (
"bufio"
"errors"
"fmt"
"io"
"strings"
"unicode/utf8"
)
const BatasByte int64 = 2 * 1024 * 1024
var ErrUkuran = errors.New("berkas melebihi 2 MiB")
var ErrUTF8 = errors.New("berkas harus UTF-8 valid")
type Hasil struct {
Nomor int
Teks string
}
func Cari(kata string, reader io.Reader) ([]Hasil, error) {
if strings.TrimSpace(kata) == "" {
return nil, errors.New("kata pencarian tidak boleh kosong")
}
data, err := io.ReadAll(io.LimitReader(reader, BatasByte+1))
if err != nil {
return nil, fmt.Errorf("gagal membaca: %w", err)
}
if int64(len(data)) > BatasByte {
return nil, ErrUkuran
}
if !utf8.Valid(data) {
return nil, ErrUTF8
}
scanner := bufio.NewScanner(strings.NewReader(string(data)))
scanner.Buffer(make([]byte, 64*1024), int(BatasByte)+1)
hasil := make([]Hasil, 0)
nomor := 0
for scanner.Scan() {
nomor++
if baris := scanner.Text(); strings.Contains(baris, kata) {
hasil = append(hasil, Hasil{Nomor: nomor, Teks: baris})
}
}
if err := scanner.Err(); err != nil {
return nil, fmt.Errorf("gagal memindai: %w", err)
}
return hasil, nil
}
Pembacaan dibatasi menjadi batas ditambah satu byte untuk mendeteksi ukuran yang melampaui ketentuan. Scanner.Buffer mengatur kemampuan membaca baris panjang, dan scanner.Err() tetap diperiksa setelah loop. Scanner mempunyai batas token; mengabaikan error dapat membuat hasil pemindaian tidak lengkap terlihat seperti sukses. Go io (diakses 2026/10), LimitReader; Go bufio (diakses 2026/10), Scanner dan Buffer.
Kode ini membaca data terbatas ke memori lebih dahulu, sehingga bukan contoh streaming untuk berkas tanpa batas. Konversi ke string dan penyimpanan hasil juga memakai memori. Jika kebutuhan Anda berkas besar, rancang alur streaming dan kebijakan panjang baris secara terpisah.
Program CLI lengkap
package main
import (
"fmt"
"io"
"os"
"strings"
"example.com/tumbas/cari-teks-go/internal/cari"
)
func run(args []string, out, errOut io.Writer) int {
if len(args) != 2 || strings.TrimSpace(args[0]) == "" {
fmt.Fprintln(errOut, "Gunakan: cari-teks <kata> <path>")
return 2
}
file, err := os.Open(args[1])
if err != nil {
fmt.Fprintln(errOut, "Gagal membuka:", err)
return 2
}
defer file.Close()
hasil, err := cari.Cari(args[0], file)
if err != nil {
fmt.Fprintln(errOut, err)
return 2
}
if len(hasil) == 0 {
return 1
}
for _, h := range hasil {
fmt.Fprintf(out, "%d:%s\n", h.Nomor, h.Teks)
}
return 0
}
func main() { os.Exit(run(os.Args[1:], os.Stdout, os.Stderr)) }
Kontrak exit code contoh: nol jika ditemukan, satu jika tidak ada kecocokan, dan dua jika argumen atau pembacaan gagal. Fungsi run menyelesaikan pekerjaannya, termasuk defer penutupan file, sebelum main memanggil os.Exit.
Dari kode/cari-teks:
go run ./cmd/cari-teks Go fixtures/catatan.txt
Keluaran yang diharapkan:
1:Belajar Go dari dasar.
3:Go memiliki goroutine.
Periksa juga huruf kecil, kata yang tidak ada, path salah, dan argumen kosong. Untuk kata yang mengandung spasi, gunakan tanda kutip. Saat memakai go run, alat Go dapat menerjemahkan status program gagal menjadi status perintahnya sendiri; gunakan executable hasil build untuk menilai kontrak exit code CLI secara langsung. Go Command (diakses 2026/10), go run.
go build -o cari-teks ./cmd/cari-teks
Pada Windows, pilih nama keluaran cari-teks.exe, lalu jalankan melalui ./cari-teks.exe di PowerShell. Di Unix, gunakan ./cari-teks. Pada PowerShell, periksa $LASTEXITCODE segera sesudah executable; di shell Unix, periksa echo $?.
Menguji CLI
go test -v ./...
go test -race ./...
Test library mencakup pencarian, nomor baris, CRLF/Unicode, input kosong, baris panjang, batas ukuran, UTF-8 tidak valid, dan kegagalan reader. Test program memeriksa fungsi run dengan buffer keluaran. File test lengkap ikut dalam ZIP; pengujian fungsi run berbeda dari pengujian proses executable yang dilakukan terpisah pada penyiapan paket.
11. Proyek API: katalog dan perhitungan harga

Ilustrasi ImageGen: belajar API pada loopback lokal. Tidak menampilkan screenshot hasil uji.
API menggunakan katalog statis dua produk. Ada endpoint baca, filter, detail, serta POST /hitung yang menghitung total tanpa menyimpan transaksi. Tidak ada login, database, atau perubahan katalog. Lingkup ini dipilih supaya Anda dapat memeriksa routing, JSON, validasi, dan status HTTP terlebih dahulu.
Manifest API
module example.com/tumbas/api-katalog-go
go 1.27.0
Semua import proyek berasal dari pustaka standar atau package dalam module yang sama. Karena tidak ada dependensi module luar, paket tidak memerlukan go.sum untuk daftar module pihak ketiga. Jangan menambahkan file checksum kosong hanya agar struktur terlihat seperti proyek lain. Go Modules Reference (diakses 2026/10), go.sum files.
Handler lengkap
package api
import (
"encoding/json/v2"
"errors"
"io"
"mime"
"net/http"
"strconv"
"strings"
"unicode/utf8"
)
type Produk struct {
ID uint64 `json:"id"`
Nama string `json:"nama"`
Harga uint64 `json:"harga"`
}
type Pesan struct {
Pesan string `json:"pesan"`
}
func produk() []Produk {
return []Produk{{1, "Buku Go", 75_000}, {2, "Buku Python", 65_000}}
}
func kirim(w http.ResponseWriter, status int, nilai any) {
data, err := json.Marshal(nilai)
if err != nil {
http.Error(w, "Gagal membuat respons", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.Header().Set("X-Content-Type-Options", "nosniff")
w.WriteHeader(status)
_, _ = w.Write(data)
}
func daftar(w http.ResponseWriter, r *http.Request) {
q := r.URL.Query().Get("q")
if !utf8.ValidString(q) || utf8.RuneCountInString(q) > 64 {
kirim(w, 400, Pesan{"q harus UTF-8 valid dan maksimal 64 rune"})
return
}
q = strings.ToLower(q)
hasil := make([]Produk, 0)
for _, p := range produk() {
if strings.Contains(strings.ToLower(p.Nama), q) {
hasil = append(hasil, p)
}
}
kirim(w, 200, hasil)
}
func detail(w http.ResponseWriter, r *http.Request) {
id, err := strconv.ParseUint(r.PathValue("id"), 10, 64)
if err != nil {
kirim(w, 400, Pesan{"ID harus angka"})
return
}
for _, p := range produk() {
if p.ID == id {
kirim(w, 200, p)
return
}
}
kirim(w, 404, Pesan{"Produk tidak ditemukan"})
}
type InputHitung struct {
ID uint64 `json:"id"`
Jumlah uint64 `json:"jumlah"`
}
type Total struct {
Total uint64 `json:"total"`
}
func hitung(w http.ResponseWriter, r *http.Request) {
media, _, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
if err != nil || media != "application/json" {
kirim(w, 415, Pesan{"Gunakan application/json"})
return
}
r.Body = http.MaxBytesReader(w, r.Body, 1024)
data, err := io.ReadAll(r.Body)
if err != nil {
var besar *http.MaxBytesError
if errors.As(err, &besar) {
kirim(w, 413, Pesan{"Body maksimal 1024 byte"})
} else {
kirim(w, 400, Pesan{"Body tidak dapat dibaca"})
}
return
}
var input InputHitung
if err := json.Unmarshal(data, &input, json.RejectUnknownMembers(true)); err != nil {
kirim(w, 400, Pesan{"JSON tidak sesuai kontrak"})
return
}
if input.Jumlah < 1 || input.Jumlah > 100 {
kirim(w, 400, Pesan{"Jumlah harus 1 sampai 100"})
return
}
for _, p := range produk() {
if p.ID == input.ID {
kirim(w, 200, Total{p.Harga * input.Jumlah})
return
}
}
kirim(w, 404, Pesan{"Produk tidak ditemukan"})
}
func New() http.Handler {
mux := http.NewServeMux()
mux.HandleFunc("GET /health", func(w http.ResponseWriter, r *http.Request) { kirim(w, 200, Pesan{"ok"}) })
mux.HandleFunc("GET /produk", daftar)
mux.HandleFunc("GET /produk/{id}", detail)
mux.HandleFunc("POST /hitung", hitung)
return mux
}
Router memakai pola method dan wildcard pada ServeMux. Dukungan tersebut diperkenalkan pada Go 1.22; panduan ini tetap memakai baseline lebih baru untuk JSON v2. GET pada pola juga melayani HEAD sesuai aturan router. Go Routing Enhancements (diakses 2026/10).
Kontrak input POST /hitung menolak field asing, JSON duplikat, body lebih dari 1.024 byte, jumlah di luar satu sampai seratus, dan produk yang tidak ada. Batas jumlah serta harga statis sengaja membuat perkalian contoh berada dalam rentang uint64. Jika data harga nantinya dapat diubah, tinjau kembali batas perkalian.
MaxBytesReader membatasi body yang dibaca handler. Ini tidak sama dengan membatasi panjang query, header, atau semua permintaan dalam server. Kode juga memeriksa tipe media sebelum membaca JSON. Go HTTP (diakses 2026/10), MaxBytesReader; Go mime (diakses 2026/10), ParseMediaType.
Respons yang ditulis handler kita menggunakan JSON. Respons bawaan router untuk rute yang tidak ditemukan dan metode yang salah dapat berbentuk teks. Untuk API publik, tetapkan kontrak error menyeluruh sebelum menambah client yang bergantung pada satu bentuk respons.
Server, timeout, dan shutdown
package main
import (
"context"
"errors"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"example.com/tumbas/api-katalog-go/internal/api"
)
func run() error {
server := &http.Server{
Addr: "127.0.0.1:3000",
Handler: api.New(),
ReadHeaderTimeout: 5 * time.Second,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 30 * time.Second,
MaxHeaderBytes: 1 << 20,
}
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
hasil := make(chan error, 1)
go func() { hasil <- server.ListenAndServe() }()
log.Println("API latihan: http://127.0.0.1:3000")
select {
case err := <-hasil:
if errors.Is(err, http.ErrServerClosed) {
return nil
}
return err
case <-ctx.Done():
}
tunggu, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := server.Shutdown(tunggu); err != nil {
_ = server.Close()
<-hasil
return err
}
if err := <-hasil; !errors.Is(err, http.ErrServerClosed) {
return err
}
return nil
}
func main() {
if err := run(); err != nil {
log.Print(err)
os.Exit(1)
}
}
Alamat 127.0.0.1:3000 membuat contoh ditujukan untuk loopback lokal. Nilai timeout adalah pilihan demonstrasi, bukan angka optimal untuk seluruh aplikasi. Shutdown memakai context dengan batas waktu dan menunggu hasil server. Go HTTP Server (diakses 2026/10), Timeouts dan Shutdown; Go signal (diakses 2026/10), NotifyContext.
Jangan mengubah alamat menjadi publik sebelum menyiapkan kebutuhan operasi dan izin akses. Contoh katalog statis tidak otomatis menjadi pola yang sesuai untuk data pengguna atau dokumen pribadi.
Mencoba API dari dua terminal
Dari kode/api-katalog:
go run ./cmd/api-katalog
Di PowerShell terminal kedua:
Invoke-RestMethod "http://127.0.0.1:3000/health"
Invoke-RestMethod "http://127.0.0.1:3000/produk?q=go"
Invoke-RestMethod -Method Post -Uri "http://127.0.0.1:3000/hitung" -ContentType "application/json" -Body '{"id":1,"jumlah":2}'
Hasil perhitungan yang diharapkan adalah objek dengan field total bernilai 150000. Untuk melihat status dan header, gunakan curl; pada Windows, sebut curl.exe bila curl di shell mengarah ke perintah lain.
curl -i "http://127.0.0.1:3000/produk/99"
| Permintaan | Hasil contoh yang diharapkan |
|---|---|
GET /health |
200, pesan ok |
GET /produk |
200, daftar dua produk |
GET /produk?q=go |
200, daftar satu produk |
GET /produk/99 |
404, produk tidak ditemukan |
GET /produk/abc |
400, ID tidak valid |
POST /produk |
405 dari router |
POST /hitung dengan input sah |
200, hasil total |
POST /hitung dengan field asing atau duplikat |
400 |
POST /hitung dengan body melebihi batas |
413 |
POST /hitung dengan tipe media lain |
415 |
Test handler dengan httptest
go test -v ./internal/api
go test -race ./...
Test menggunakan httptest.NewRecorder dan request buatan untuk memeriksa handler tanpa membuka port. Cakupannya mencakup status, isi filter, total harga, dan hasil kosong sebagai array. Seluruh file internal/api/api_test.go tersedia dalam ZIP. Go httptest (diakses 2026/10), ResponseRecorder dan NewRequest.
Test tersebut berbeda dari pemeriksaan jaringan. Ia tidak menilai konfigurasi proxy, TLS, firewall, atau jalur internet. Gunakan masing-masing jenis pemeriksaan sesuai pertanyaan yang ingin dijawab, dan jangan menyebut test handler sebagai audit keamanan server.
12. Concurrency dan race detector
Goroutine dapat mengakses ruang alamat yang sama. Akses bersama yang tidak disinkronkan dapat menghasilkan data race. Go menyediakan race detector melalui opsi -race, tetapi detector hanya dapat menemukan masalah pada jalur yang benar-benar dijalankan saat pengujian. Go Race Detector (diakses 2026/10), Introduction dan How To Use.
Pada contoh 16, buffer channel, jumlah produsen, dan waktu menunggu dirancang bersama. Jangan meningkatkan jumlah produsen tanpa meninjau kapasitas dan urutan penerima. Pada proyek nyata, pikirkan juga apa yang terjadi jika konsumen gagal, request dibatalkan, atau hasil tidak lagi dibutuhkan.
Saran editorial kami adalah memulai concurrency ketika ada tugas yang dapat dibatasi dengan jelas. Catat siapa yang menghasilkan nilai, siapa yang menutup channel, dan siapa yang menunggu. Bila Anda belum bisa menjelaskan ketiganya, kecilkan contoh sebelum menambahkan goroutine baru.
Tidak ada klaim performa pada latihan ini. Menambah goroutine dapat menambah koordinasi serta pemakaian memori. Untuk menilai manfaatnya, tentukan beban kerja dan ukuran keberhasilan, lalu ukur implementasi yang benar-benar dipakai.
13. Keamanan, pembaruan, dan govulncheck
govulncheck membantu menemukan kerentanan yang diketahui dengan meninjau dependensi dan jalur pemanggilan yang relevan. Ia merupakan alat tambahan, bukan jaminan aplikasi bebas masalah. Tutorial resmi menjelaskan cara memasang serta menjalankannya. Go Govulncheck (diakses 2026/10), Overview.
go install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck ./...
Perintah instalasi ini memerlukan akses jaringan dan menambahkan alat di luar paket latihan. @latest dapat berubah; untuk proses tim yang perlu diulang persis, catat versi alat yang dipakai. Artikel tidak mengklaim hasil pemindaian jika perintah tersebut belum dijalankan pada proyek Anda.
Untuk evaluasi aplikasi, pisahkan keselamatan memori, validasi input, identitas pengguna, izin akses data, serta operasi server. Sebagai latihan desain, tanyakan apakah pengguna A boleh membaca objek pengguna B. Jawaban itu harus dinyatakan dalam aturan aplikasi dan diperiksa; pemilihan Go tidak menggantikan keputusan tersebut.
Jika ingin inspirasi jenis aplikasi berikutnya, baca 100 Proyek GitHub Pengganti Software Berbayar di Tumbas.in. Gunakan sebagai bacaan internal untuk mengenali kebutuhan, kemudian periksa dokumentasi proyek yang dipilih sebelum mengadopsi kode, lisensi, atau dependensinya.
14. Build dan pertanyaan hosting
Dari folder module masing-masing, contoh perintah build adalah:
go build -o api-katalog ./cmd/api-katalog
Pada Windows, gunakan nama keluaran dengan .exe sesuai kebiasaan lingkungan tersebut. Hasil build perlu cocok dengan sistem operasi dan arsitektur tujuan. Jangan menganggap binary dari Linux dapat langsung dipakai di Windows atau sebaliknya. GOOS, GOARCH, dan pemakaian cgo memengaruhi kebutuhan target build. Go Command (diakses 2026/10), Build dan Environment variables.
Untuk shared hosting, mintalah jawaban penyedia mengenai izin executable, proses yang terus aktif, pengaturan port, proxy, log, dan prosedur mulai ulang. Keberadaan terminal atau kemampuan mengunggah file belum cukup menjelaskan apakah aplikasi dapat dioperasikan sesuai kebutuhan.
Untuk belajar, komputer lokal sudah menjadi lingkungan yang tepat bagi contoh ini. Jangan memindahkan website utama hanya agar bisa mencoba Go. Selesaikan fitur kecil, catat cara membangun dan menghentikan program, lalu pilih lingkungan penerapan berdasarkan kebutuhan yang sudah Anda pahami.
15. Troubleshooting yang perlu diperiksa
| Gejala | Hal yang diperiksa | Langkah latihan |
|---|---|---|
go tidak dikenali |
Instalasi dan PATH terminal | Buka terminal baru lalu cek versi |
| Versi terlalu lama | go version dan baris go |
Gunakan compiler yang sesuai baseline |
| Import JSON v2 gagal | Versi compiler dan jalur import | Jangan mengganti API tanpa meninjau kompatibilitas |
go.mod tidak ditemukan |
Direktori kerja | Masuk ke salah satu dari tiga module |
| Variabel/import tidak dipakai | Deklarasi yang tidak diperlukan | Pakai untuk tujuan nyata atau hapus |
| CLI tidak menemukan file | Path relatif dan direktori kerja | Coba fixture dari folder proyek |
| Hasil pencarian kosong | Huruf besar dan kata pencarian | Coba kata Go pada fixture |
| Program concurrent macet | Pengirim, penerima, buffer, dan penutupan | Kembalikan dulu ke contoh asli |
| API gagal bind | Port 3000 sudah dipakai | Hentikan proses latihan yang terdahulu |
| API memberi 413 | Panjang body | Coba input kecil yang sah |
-race gagal dibangun |
Dukungan target dan compiler C | Periksa prasyarat race detector |
Prasyarat race detector dijelaskan dalam Go Race Detector (diakses 2026/10), Requirements. Tabel lainnya merupakan saran pemeriksaan untuk kode dan struktur paket ini.
Jika muncul banyak pesan, baca error pertama yang berkaitan dengan sumber Anda. Simpan hasilnya, ubah satu hal, lalu ulangi pemeriksaan yang relevan. Mengganti versi toolchain, struktur folder, dan banyak kode sekaligus akan menyulitkan penelusuran sebab masalah.
16. Memformat, memeriksa, dan menguji kode

Ilustrasi ImageGen: peninjauan kode. Hasil uji aktual tersedia sebagai teks dan JSON dalam paket.
Jalankan dari masing-masing module:
gofmt -w .
go vet ./...
go test -race -count=1 ./...
go build ./...
gofmt memformat sumber, go vet mencari konstruksi yang mencurigakan, dan go test menjalankan pengujian. Ketiganya menjawab pertanyaan yang berbeda. Jangan menganggap format rapi sebagai bukti logika sudah benar. Go gofmt (diakses 2026/10); Go vet (diakses 2026/10); Go testing (diakses 2026/10).
Pada penyiapan paket ini, kode diperiksa memakai go version go1.27.3 linux/amd64 di Linux. Dua puluh contoh dijalankan dan stdout-nya cocok dengan keluaran dalam artikel. Tiga contoh salah ditolak compiler dengan pesan yang diharapkan. Format, go vet, serta build ketiga module berhasil.
Sebanyak 46 kasus uji akhir lolos dengan race detector: enam pada validasi dasar, enam belas pada CLI, dan dua puluh empat pada API. Penghitungan ini memakai kasus/subtest paling dalam; induk subtest tidak dihitung lagi. Contoh goroutine dan channel juga dijalankan dengan go run -race. Empat skenario executable CLI diperiksa terpisah untuk keluaran dan exit code.
Server lokal diperiksa melalui sebelas permintaan HTTP. Perilaku JSON duplikat, body besar, status error, total harga, penghentian melalui SIGINT, serta exit code saat port sudah dipakai ikut diperiksa. Pengujian module dilakukan dengan akses unduhan module dimatikan. Pada lingkungan penyiapan, VCS stamping dinonaktifkan menggunakan -buildvcs=false; pengaturan itu dicatat dalam log.
Ini pemeriksaan fungsional lokal, bukan uji beban, benchmark, atau audit keamanan. Windows/macOS belum diuji. govulncheck dijelaskan sebagai langkah opsional dan belum dijalankan pada penyiapan ini. Rincian perintah tersedia di hasil-uji.txt dan hasil terstruktur di hasil-uji.json.
Tidak semua package contoh mempunyai unit test sendiri. Keluaran 20 program diperiksa dengan menjalankannya; pengujian unit/subtest berfokus pada validasi, CLI, dan handler API. Penjelasan ini membantu membedakan jumlah kasus yang lolos dari banyaknya package atau blok kode dalam artikel.
Jika Anda mengubah contoh setelah mengunduh ZIP, jalankan kembali pemeriksaan untuk bagian tersebut. Program yang lolos compile masih dapat memiliki aturan bisnis yang salah, sehingga periksa juga keluaran dan skenario gagal yang Anda perlukan.
17. Rencana belajar empat minggu
Rencana ini adalah usulan editorial, bukan janji menguasai Go dalam satu bulan. Perlambat bagian yang masih sulit dan kecilkan ruang lingkup proyek bila waktu Anda terbatas.
Minggu pertama: selesaikan contoh satu sampai sembilan. Pahami fungsi, nilai, slice, map, dan interface. Ubah data pada setiap contoh dan tulis prediksi sebelum menjalankannya. Jangan menambah framework sampai alur dasar dapat dijelaskan.
Minggu kedua: selesaikan error, Unicode, JSON, defer, file, dan generic. Buat satu fungsi parsing dengan tiga kasus input. Perhatikan perbedaan input tidak sah, data tidak ditemukan, dan kegagalan operasi I/O.
Minggu ketiga: kerjakan concurrency, context, dan test, lalu jalankan CLI. Tuliskan siapa yang mengirim, menerima, menutup channel, dan menunggu. Untuk CLI, tambah satu fitur kecil dengan aturan yang jelas, misalnya menampilkan jumlah kecocokan.
Minggu keempat: jalankan API dan baca seluruh testnya. Tambahkan satu produk atau satu validasi, lalu periksa status dan body. Jika ingin menambah penyimpanan, rancang bentuk data, batas perubahan, identitas pengguna, dan cara pemulihan sebelum memilih database.
Pada akhir latihan, buat catatan satu halaman: cara menjalankan, versi Go, fitur yang sudah diuji, batas yang belum ditangani, dan satu perubahan berikutnya. Catatan itu memberi titik mulai yang jelas saat Anda kembali belajar.
18. FAQ belajar Go/Golang
Apakah Go dan Golang berbeda?
Nama bahasanya adalah Go. Golang merupakan sebutan yang lazim dipakai untuk membantu membedakan pencarian. Gunakan nama Go pada rujukan resmi dan baca package berdasarkan jalur importnya. Go FAQ (diakses 2026/10), Go or Golang.
Apakah harus belajar C dahulu?
Panduan ini tidak mensyaratkannya. Mulai dari fungsi, data, dan error. Pengetahuan sistem akan membantu pada topik lanjutan, tetapi bukan alasan menunda program pertama yang kecil dan dapat diperiksa.
Apakah perlu Gin, Echo, atau framework lain?
Untuk latihan ini tidak. net/http menyediakan komponen yang diperlukan proyek API. Pertimbangkan framework setelah Anda dapat menjelaskan kebutuhan yang ingin disederhanakan, lalu periksa dokumentasi dan pemeliharaannya saat memilih. Go HTTP (diakses 2026/10).
Apakah goroutine sama dengan satu thread sistem operasi?
Goroutine dikelola runtime dan tidak perlu dipahami sebagai pemetaan satu banding satu ke thread OS. Gunakan model goroutine serta sinkronisasi yang dijelaskan dokumentasi. Go FAQ (diakses 2026/10), Goroutines.
Apakah channel membuat semua data otomatis aman?
Tidak ada alasan untuk mengabaikan akses data bersama. Race detector membahas perlunya sinkronisasi pada akses concurrent yang berkonflik. Saran kami adalah meninjau pemilik data, urutan akses, dan pembatalan meskipun program memakai channel. Go Race Detector (diakses 2026/10).
Mengapa artikel memakai JSON v2?
Baseline latihan adalah Go 1.27, dan dokumentasi terbaru menjelaskan JSON v2 serta perbedaan default terhadap v1. Pilihan ini memungkinkan contoh menolak sejumlah input ambigu tanpa menyamarkan perbedaan kompatibilitas. Go JSON v2 (diakses 2026/10), Security Considerations.
Apakah seluruh contoh dapat berjalan offline?
Kode hanya memakai pustaka standar dan package lokal. Setelah toolchain yang sesuai tersedia, build latihan tidak memerlukan unduhan module pihak ketiga. Halaman sumber, pemasangan toolchain, dan instalasi opsional govulncheck tetap memerlukan jaringan. Pengaturan offline yang benar-benar digunakan saat uji dicatat dalam paket.
Apakah kode API siap dipublikasikan untuk data nyata?
Kode disiapkan untuk latihan lokal dengan katalog statis. Ia belum menyediakan kebutuhan aplikasi produksi seperti autentikasi, penyimpanan persisten, pengelolaan rahasia, konfigurasi proxy, atau prosedur operasional lengkap. Gunakan sebagai titik mulai belajar, lalu rancang kebutuhan aplikasi Anda secara khusus.
Mulai dari program kecil yang dapat dijelaskan
Buka kode/dasar, jalankan contoh pertama, lalu ubah satu hal. Sesudah alur dasar jelas, gunakan proyek CLI untuk menyatukan input, pembacaan, dan error. Lanjutkan ke API untuk mempelajari kontrak request serta respons.
Pilih satu perubahan berikutnya yang dapat diuji. Tuliskan hasil yang diinginkan sebelum mengubah kode, periksa skenario gagal, lalu simpan cara menjalankannya. Dengan kebiasaan ini, latihan Go menghasilkan program yang dapat Anda pahami dan lanjutkan sendiri.
Sumber resmi dan bacaan lanjutan
Tanggal akses: 22 Oktober 2026. Bulan pada label sitasi menunjukkan waktu akses. Contoh kode adalah latihan asli; dokumentasi dipakai untuk memeriksa sintaks dan perilaku.
- [Go 1.27, diakses 2026/10] Go Project. "Go 1.27 Release Notes - The Go Programming Language". Buka sumber.
- [Go JSON v2, diakses 2026/10] Go Project. "json package - encoding/json/v2 - Go Packages". Buka sumber.
- [Go Specification, diakses 2026/10] Go Project. "The Go Programming Language Specification - The Go Programming Language". Buka sumber.
- [Go FAQ, diakses 2026/10] Go Project. "Frequently Asked Questions (FAQ) - The Go Programming Language". Buka sumber.
- [Go HTTP, diakses 2026/10] Go Project. "http package - net/http - Go Packages". Buka sumber.
- [Go GC Guide, diakses 2026/10] Go Project. "A Guide to the Go Garbage Collector - The Go Programming Language". Buka sumber.
- [Go Modules, diakses 2026/10] Go Project. "go.mod file reference - The Go Programming Language". Buka sumber.
- [Go Tour Concurrency, diakses 2026/10] Go Project. "A Tour of Go". Buka sumber.
- [Go Context, diakses 2026/10] Go Project. "context package - context - Go Packages". Buka sumber.
- [Go Wiki, diakses 2026/10] Go Project. "Go Wiki: TableDrivenTests - The Go Programming Language". Buka sumber.
- [Go Install, diakses 2026/10] Go Project. "Download and install - The Go Programming Language". Buka sumber.
- [Go Release Policy, diakses 2026/10] Go Project. "Release History - The Go Programming Language". Buka sumber.
- [Go Command, diakses 2026/10] Go Project. "go command - cmd/go - Go Packages". Buka sumber.
- [Go Getting Started, diakses 2026/10] Go Project. "Tutorial: Get started with Go - The Go Programming Language". Buka sumber.
- [Go fmt, diakses 2026/10] Go Project. "Go fmt". Buka sumber.
- [Effective Go, diakses 2026/10] Go Project. "Effective Go - The Go Programming Language". Buka sumber.
- [Go Slices, diakses 2026/10] Go Project. "Go Slices: usage and internals - The Go Programming Language". Buka sumber.
- [Go slices, diakses 2026/10] Go Project. "slices package - slices - Go Packages". Buka sumber.
- [Go Maps, diakses 2026/10] Go Project. "Go maps in action - The Go Programming Language". Buka sumber.
- [Go strings, diakses 2026/10] Go Project. "strings package - strings - Go Packages". Buka sumber.
- [Go errors, diakses 2026/10] Go Project. "errors package - errors - Go Packages". Buka sumber.
- [Go Strings Blog, diakses 2026/10] Go Project. "Strings, bytes, runes and characters in Go - The Go Programming Language". Buka sumber.
- [Go UTF8, diakses 2026/10] Go Project. "utf8 package - unicode/utf8 - Go Packages". Buka sumber.
- [Go Defer Blog, diakses 2026/10] Go Project. "Defer, Panic, and Recover - The Go Programming Language". Buka sumber.
- [Go os, diakses 2026/10] Go Project. "os package - os - Go Packages". Buka sumber.
- [Go os, diakses 2026/10] Go Project. "os package - os - Go Packages". Buka sumber.
- [Go Generics Tutorial, diakses 2026/10] Go Project. "Tutorial: Getting started with generics - The Go Programming Language". Buka sumber.
- [Go sync, diakses 2026/10] Go Project. "sync package - sync - Go Packages". Buka sumber.
- [Go Tour Channels, diakses 2026/10] Go Project. "A Tour of Go". Buka sumber.
- [Go Tour Range and Close, diakses 2026/10] Go Project. "A Tour of Go". Buka sumber.
- [Go httptest, diakses 2026/10] Go Project. "httptest package - net/http/httptest - Go Packages". Buka sumber.
- [Go io, diakses 2026/10] Go Project. "io package - io - Go Packages". Buka sumber.
- [Go testing, diakses 2026/10] Go Project. "testing package - testing - Go Packages". Buka sumber.
- [Go bufio, diakses 2026/10] Go Project. "bufio package - bufio - Go Packages". Buka sumber.
- [Go Modules Reference, diakses 2026/10] Go Project. "Go Modules Reference - The Go Programming Language". Buka sumber.
- [Go Routing Enhancements, diakses 2026/10] Go Project. "Routing Enhancements for Go 1.22 - The Go Programming Language". Buka sumber.
- [Go HTTP, diakses 2026/10] Go Project. "http package - net/http - Go Packages". Buka sumber.
- [Go mime, diakses 2026/10] Go Project. "mime package - mime - Go Packages". Buka sumber.
- [Go HTTP Server, diakses 2026/10] Go Project. "http package - net/http - Go Packages". Buka sumber.
- [Go signal, diakses 2026/10] Go Project. "signal package - os/signal - Go Packages". Buka sumber.
- [Go Race Detector, diakses 2026/10] Go Project. "Data Race Detector - The Go Programming Language". Buka sumber.
- [Go Govulncheck, diakses 2026/10] Go Project. "Tutorial: Find and fix vulnerable dependencies with govulncheck - The Go Programming Language". Buka sumber.
- [100 Proyek GitHub Pengganti Software Berbayar di Tumbas.in, diakses 2026/10] Tumbas.in. "100 Proyek GitHub Bernilai Miliaran Pengganti Software Berbayar". Buka sumber.
- [Go gofmt, diakses 2026/10] Go Project. "gofmt command - cmd/gofmt - Go Packages". Buka sumber.
- [Go vet, diakses 2026/10] Go Project. "vet command - cmd/vet - Go Packages". Buka sumber.
- [Go FAQ, diakses 2026/10] Go Project. "Frequently Asked Questions (FAQ) - The Go Programming Language". Buka sumber.
Komentar (0)
Belum ada komentar. Jadilah yang pertama berkomentar!
Tinggalkan Komentar