Deploy aplikasi Go dimulai dari satu berkas: binary. Compiler Go membungkus kode kita, bagian standard library yang dipakai, dan runtime Go ke dalam satu file executable — tanpa installer, tanpa daftar dependensi runtime, dan tanpa interpreter. Model distribusi ini membuat langkah pertama operasional sebuah aplikasi menjadi sangat singkat: bangun binary, salin ke server, jalankan. Chapter ini membahas cara menghasilkan binary siap production dengan go build, mengatur nama outputnya, dan memverifikasi bahwa binary berdiri sendiri tanpa bergantung pada library sistem.
Program yang Akan Kita Bangun #
Berkas build-demo.go pada bagian bawah halaman adalah program mini bernama sapa yang akan kita bangun berulang kali sepanjang section ini. Program tersebut mencetak identitas dirinya supaya hasil setiap build bisa kita bandingkan:
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println("sapa v0.1.0")
fmt.Printf("platform: %s/%s\n", runtime.GOOS, runtime.GOARCH)
fmt.Println("compiler:", runtime.Version())
}Output yang Dihasilkan:
sapa v0.1.0
platform: linux/amd64
compiler: go1.27.2Mari kita telaah baris demi baris program di atas:
- Baris 1 (
package main): mendeklarasikan packagemain, penanda modul executable —go buildhanya menghasilkan binary untuk package bertipemain. - Baris 3–6 (
import ...): mengimporfmtuntuk mencetak output danruntimeuntuk membaca identitas platform. - Baris 8 (
func main()): titik masuk program; baris-baris di dalamnya dijalankan saat binary dieksekusi. - Baris 9 (
fmt.Println("sapa v0.1.0")): mencetak banner versi — nanti diotomatisasi lewat-ldflagspada chapter berikutnya. - Baris 10 (
fmt.Printf(...)): mencetak kombinasiruntime.GOOSdanruntime.GOARCH, yaitu sistem operasi dan arsitektur yang menjadi target build. - Baris 11 (
fmt.Println("compiler:", ...)): mencetakruntime.Version(), versi toolchain yang tercetak di dalam binary, bukan dibaca saat dijalankan.
go build dan Nama Output #
Perintah go run mengompilasi program ke build cache, mengeksekusinya sekali, lalu membuang executable-nya. Perintah go build menghasilkan berkas executable permanen. Siapkan modul kecil, salin isi build-demo.go ke main.go, lalu bangun:
mkdir sapa-deploy && cd sapa-deploy
go mod init example.com/sapa
# simpan isi build-demo.go sebagai main.go
go build
ls -lh sapaOutput yang Dihasilkan:
-rwxrwxr-x 1 z z 2.3M Oct 13 13:26 sapaPerhatikan bahwa berkas hasil build bernama sapa, bukan main. Aturan penamaan go build mengikuti komponen terakhir dari path module (example.com/sapa → sapa), bukan nama berkas sumber. Untuk nama berbeda, gunakan flag -o:
go build -o sapa-server
ls -lh sapa-serverOutput yang Dihasilkan:
-rwxrwxr-x 1 z z 2.3M Oct 13 13:26 sapa-serverBinary hasil -o inilah yang akan kita salin ke server pada chapter-chapter berikutnya.
go build vs go install #
Perintah go install juga mengompilasi, tetapi menaruh hasilnya di direktori GOBIN (bawaannya $HOME/go/bin) alih-alih direktori kerja. Pola ini cocok untuk alat CLI yang ingin tersedia di PATH kita, bukan untuk artefak rilis:
GOBIN=$PWD/bin go install
ls -lh sapa-server bin/sapaOutput yang Dihasilkan:
-rwxrwxr-x 1 z z 2.3M Oct 13 13:26 bin/sapa
-rwxrwxr-x 1 z z 2.3M Oct 13 13:26 sapa-server| Perintah | Lokasi hasil | Kegunaan utama |
|---|---|---|
go build | Direktori kerja, atau -o | Artefak yang didistribusikan ke server |
go install | GOBIN | Alat CLI pribadi di PATH developer |
Binary Statis dan Portabilitas #
Binary murni Go tidak membutuhkan dynamic library sistem. Kita bisa membuktikannya dengan ldd, alat yang menampilkan dynamic library yang dibutuhkan sebuah executable:
ldd sapaOutput yang Dihasilkan:
not a dynamic executablePesan tersebut muncul di standard error dan ldd keluar dengan status 1 — keduanya normal, dan justru konfirmasi bahwa binary berdiri sendiri: satu berkas sapa bisa disalin ke server Linux x86-64 mana pun dan langsung berjalan.
Situasi berubah ketika program memakai package dengan varian cgo. Program kecil berikut hanya memanggil net.SplitHostPort, tetapi package net memuat varian cgo yang aktif bila kompiler C tersedia di mesin build:
package main
import (
"fmt"
"net"
)
func main() {
host, port, err := net.SplitHostPort("db.internal:5432")
if err != nil {
fmt.Println("galat:", err)
return
}
fmt.Printf("host=%s port=%s\n", host, port)
}Bangun dua varian dengan CGO_ENABLED=1 (default di mesin berkompiler C) dan CGO_ENABLED=0, lalu bandingkan hasil ldd-nya (alamat memori dipangkas lewat awk supaya output stabil):
CGO_ENABLED=1 go build -o netdemo-cgo
CGO_ENABLED=0 go build -o netdemo-static
ls -lh netdemo-cgo netdemo-static
ldd netdemo-cgo | awk '{print $1}'
ldd netdemo-static 2>&1Output yang Dihasilkan:
-rwxrwxr-x 1 z z 2.6M Oct 13 13:26 netdemo-cgo
-rwxrwxr-x 1 z z 2.6M Oct 13 13:26 netdemo-static
linux-vdso.so.1
libc.so.6
/lib64/ld-linux-x86-64.so.2
not a dynamic executableVarian netdemo-cgo terikat pada glibc (libc.so.6 dan loader /lib64/ld-linux-x86-64.so.2), sehingga gagal berjalan di Alpine ber-musl maupun di image scratch yang tanpa library. Varian netdemo-static bekerja di keduanya; output programnya sama (host=db.internal port=5432) karena perbedaannya murni di lapisan linking.
Verifikasi Binary dan Reproducibility #
Sebelum binary didistribusikan, verifikasi formatnya dengan file dan pastikan build kita bisa direproduksi. Perintah file membaca header executable — hasil aslinya untuk sapa:
sapa: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, Go BuildID=bBU1vLaeL8r_8c9_ldi1/-Xvmizuf-YIdrxTMB1ip/77u6xioSe0G0IkWAWrfr/y3Lx2Q0uWQWHrUQGgSNE, BuildID[sha1]=470466e4f03413b02127bc0e5d72eaee621eaf7e, with debug_info, not strippedKemudian bangun ulang dan bandingkan checksum:
go build && md5sum sapa
go build && md5sum sapaOutput yang Dihasilkan:
0b11034d5cb167a90ae854eee95f8c1c sapa
0b11034d5cb167a90ae854eee95f8c1c sapaChecksum yang identik membuktikan source dan flag yang sama menghasilkan binary byte demi byte identik pada toolchain yang sama — properti yang membuat checksum layak dilampirkan pada setiap rilis.
Binary 2.3M ini masih memuat informasi debug dan path direktori kerja — jejak yang bisa dipangkas sekaligus diisi nomor versi. Chapter Build Flags membahas keduanya.
Referensi #
- Dokumentasi perintah go
— referensi resmi
go build,go install, dan seluruh subperintah. - Compile packages and dependencies — aturan resmi penamaan output executable.
- Download and install Go — panduan resmi instalasi toolchain.
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
build-demo.go
Unduh berkaspackage main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println("sapa v0.1.0")
fmt.Printf("platform: %s/%s\n", runtime.GOOS, runtime.GOARCH)
fmt.Println("compiler:", runtime.Version())
}