Cara menulis kode Go

Pendahuluan

Dokumen ini mendemonstrasikan cara membuat sebuah paket Go yang sederhana dan memperkenalkan perkakas go, cara standar untuk mengambil, membuat, dan memasang paket-paket dan program Go.

Perkakas go membutuhkan programmer untuk menyusun kode dengan cara tertentu. Mohon baca dokumen ini dengan cermat. Dokumen ini menjelaskan cara paling mudah untuk memulai pemrograman Go.

Organisasi kode

Ikhtisar

  • Pemrogram Go biasanya menyimpan semua kode Go dalam sebuah ruang-kerja (workspace).

  • Sebuah ruang-kerja memiliki banyak repositori dengan version control (misalnya, yang dikelola oleh Git).

  • Setiap repositori mengandung satu atau lebih paket.

  • Setiap paket terdiri dari satu atau lebih berkas kode Go dalam sebuah direktori.

  • Path ke sebuah direktori paket menentukan nama pada import.

Ingatlah bahwa cara ini berbeda dengan lingkungan bahasa pemrograman lainnya yang mana setiap proyek memiliki ruang-kerja yang terpisah dan ruang-kerja tersebut biasanya terikat dengan sebuah repositori dan version control.

Ruang-kerja

Sebuah ruang-kerja yaitu hierarki direktori dengan dua sub-direktori di dalamnya,

  • src menyimpan berkas kode Go, dan

  • bin menyimpan program yang dapat dieksekusi.

Perkakas go membuat dan memasang program ke direktori bin.

Sub direktori dari src biasanya menyimpan beberapa repositori dengan version control (seperti Git atau Mercurial) yang menyimpan satu atau lebih sumber paket.

Untuk memberikan gambaran bagaimana bentuk sebuah ruang-kerja, berikut contohnya,

bin/
    hello                          # program yang dapat dieksekusi
    outyet                         # program yang dapat dieksekusi
src/
    github.com/golang/example/
        .git/                      # metadata repositori Git
	hello/
	    hello.go               # sumber program
	outyet/
	    main.go                # sumber program
	    main_test.go           # sumber tes
	stringutil/
	    reverse.go             # sumber paket
	    reverse_test.go        # sumber tes
    golang.org/x/image/
        .git/                      # metadata repositori Git
	bmp/
	    reader.go              # sumber paket
	    writer.go              # sumber paket
    ... (dan repositori dan paket lainnya) ...

Hierarki di atas memperlihatkan sebuah ruang-kerja yang terdiri dari dua repositori (example dan image). Repositori example memiliki dua program (hello dan outyet) dan sebuah pustaka (stringutil). Repositori image memiliki paket bmp dan beberapa paket lainnya.

Sebuah ruang-kerja pada umumnya memiliki banyak sumber repositori yang mengandung banyak paket dan program. Umumnya, pemrogram Go menyimpan semua sumber kode Go dan dependensinya dalam sebuah ruang-kerja.

Ingatlah bahwa symbolic link sebaiknya tidak digunakan untuk berkas atau direktori di dalam ruang-kerja.

Program dan pustaka dibuat dari beragam sumber paket. Kita akan bahas perbedaan dari keduanya nanti

Variabel lingkungan GOPATH

Variabel lingkungan GOPATH menentukan lokasi dari ruang-kerja. Standar lokasinya yaitu direktori bernama go di dalam home direktori, seperti $HOME/go pada sistem Unix, $home/go pada sistem Plan 9, dan %USERPROFILE%\go (biasanya C:\Users\NamaAnda\go) pada sistem Windows.

Jika ingin bekerja pada lokasi yang lain, kita perlu mengatur GOPATH ke lokasi direktori yang diinginkan. (Pengaturan yang umum lainnya yaitu men set GOPATH=$HOME.) Ingatlah bahwa GOPATH tidak boleh sama dengan lokasi dari instalasi Go.

Perintah go env GOPATH akan menampilkan nilai dari GOPATH; ia akan menampilkan lokasi standar jika variabel lingkungan tidak diset.

Untuk memudahkan, tambahkan sub direktori bin dari ruang-kerja ke dalam variabel lingkungan PATH:

$ export PATH=$PATH:$(go env GOPATH)/bin

Skrip-skrip pada bagian selanjutnya dari dokumen ini menggunakan $GOPATH untuk lebih singkat. Supaya skrip dapat berjalan bila GOPATH tidak diset, kita bisa menggantinya dengan $HOME/go atau jalankan:

$ export GOPATH=$(go env GOPATH)

Untuk belajar lebih lanjut tentang variabel lingkungan GOPATH, lihat go help gopath.

Import path

Sebuah import path yaitu sebuah string yang mengidentifikasi dan membedakan sebuah paket. Import path dari sebuah paket berhubungan dengan lokasinya di dalam sebuah ruang-kerja atau dalam sebuah repositori (dijelaskan di bawah).

Paket-paket dari pustaka standar menggunakan nama import path yang pendek seperti "fmt" dan "net/http". Untuk paket sendiri, sebaiknya pilihlah sebuah nama dasar path yang tidak konflik dengan paket standar atau pustaka eksternal lainnya.

Jika menyimpan kode dalam sebuah repositori, maka harus menggunakan root dari sumber repositori sebagai dasar path. Misalnya, jika menggunakan akun Github pada github.com/user, maka itulah yang menjadi dasar path.

Ingatlah bahwa tidak perlu menyimpan kode ke sebuah repositori luar untuk dapat menggunakan sebuah paket. Hanya saja, lebih baik biasakan untuk menyusun kode untuk berjaga-jaga kemungkinan dimuat di repositori luar nantinya. Pada praktiknya, kita bisa memilih nama path apa pun, selama ia unik dengan pustaka standar.

Sebagai contoh dalam dokumen ini, kita akan menggunakan github.com/user sebagai dasar path. Buat direktori dalam ruang-kerja untuk menyimpan sumber kode:

$ mkdir -p $GOPATH/src/github.com/user

Program pertama

Untuk mengompilasi dan menjalankan sebuah program sederhana, pertama pilih sebuah path untuk paket (kita akan gunakan github.com/user/hello) dan buat direktori untuk paket tersebut di dalam ruang-kerja:

$ mkdir $GOPATH/src/github.com/user/hello

Selanjutnya, buat sebuah berkas bernama hello.go di dalam direktori tersebut, yang berisi kode Go berikut.

package main

import "fmt"

func main() {
	fmt.Println("Hello, world.")
}

Sekarang kita bisa membuat dan memasang program tersebut dengan perkakas go:

$ go install github.com/user/hello

Ingatlah bahwa program tersebut bisa dijalankan di mana pun dalam sistem. Perkakas go mencari sumber kode dengan melihat paket github.com/user/hello di dalam ruang-kerja yang dispesifikasikan oleh GOPATH.

Kita bisa mengindahkan path paket jika menjalankan go install dari dalam direktori paket:

$ cd $GOPATH/src/github.com/user/hello
$ go install

Perintah tersebut membangun program hello, menghasilkan sebuah binari yang dapat dieksekusi. Perintah tersebut kemudian memasang binari tersebut ke direktori bin di ruang-kerja sebagai hello (atau, pada Windows, hello.exe). Pada contoh ini, binari tersebut akan dibuat di $GOPATH/bin/hello, atau sama dengan $HOME/go/bin/hello.

Perkakas go akan menampilkan pesan eror bila terjadi kesalahan, jadi bila tidak ada eror yang ditampilkan, berarti perintah tersebut dieksekusi dengan sukses.

Anda sekarang dapat menjalankan program tersebut dengan cara:

$ $GOPATH/bin/hello
Hello, world.

Atau, bila telah menambahkan $GOPATH/bin ke dalam PATH, tinggal mengetikan nama program:

$ hello
Hello, world.

Jika menggunakan sistem source control (misalnya, Git), sekarang adalah saat yang bagus untuk menginisiasi repositori, menambahkan berkas, dan melakukan commit yang pertama. Sekali lagi, langkah ini adalah opsional: tidak perlu menggunakan source control untuk menulis kode Go.

$ cd $GOPATH/src/github.com/user/hello
$ git init
Initialized empty Git repository in /home/user/go/src/github.com/user/hello/.git/
$ git add hello.go
$ git commit -m "commit pertama"
[master (root-commit) 0b4507d] initial commit
 1 file changed, 1 insertion(+)
 create mode 100644 hello.go

Memuat kode ke repositori luar sengaja diindahkan sebagai latihan bagi pembaca.

Pustaka pertama

Sekarang mari kita coba membuat sebuah paket pustaka dan menggunakannya dalam program hello.

Langkah pertama yaitu memilih path untuk paket pustaka (kita akan gunakan github.com/user/stringutil) dan membuat direktori paket:

$ mkdir $GOPATH/src/github.com/user/stringutil

Selanjutnya, buat sebuah berkas dengan nama reverse.go di dalam direktori tersebut yang berisi:

// Package stringutil berisi fungsi-fungsi untuk bekerja dengan strings.
package stringutil

// Reverse mengembalikan sebuah string yang dibalik dari kanan ke kiri.
func Reverse(s string) string {
	r := []rune(s)
	for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
		r[i], r[j] = r[j], r[i]
	}
	return string(r)
}

Sekarang, tes apakah paket tersebut dapat di- compile dengan go build:

$ go build github.com/user/stringutil

Atau, jika sekarang berada dalam direktori sumber paket, tinggal:

$ go build

Perintah tersebut tidak akan membuat berkas apa pun. Namun, ia akan menyimpan paket yang telah terkompilasi di dalam cache internal.

Setelah memastikan paket stringutil dapat dibangun, ubah hello.go (yang ada di $GOPATH/src/github.com/user/hello) untuk menggunakan paket stringutil:

package main

import (
	"fmt"

	"github.com/user/stringutil"
)

func main() {
	fmt.Println(stringutil.Reverse("!oG ,olleH"))
}

Pasang kembali program hello:

$ go install github.com/user/hello

Jalankan versi terbaru dari program tersebut, akan terlihat pesan yang dibalik:

$ hello
Hello, Go!

Setelah mengikuti langkah-langkah di atas, ruang-kerja akan seperti berikut:

bin/
    hello                 # program yang dapat dieksekusi
src/
    github.com/user/
        hello/
            hello.go      # sumber program
        stringutil/
            reverse.go    # sumber paket

Nama paket

Perintah pertama dalam sebuah sumber kode Go haruslah

package name

yang mana name adalah nama untuk paket yang di- import. (Semua berkas di dalam sebuah paket harus menggunakan nama yang sama.)

Konvensi dari Go yaitu nama paket adalah elemen terakhir dari import path: paket yang diimpor dengan "crypto/rot13" seharusnya bernama rot13.

Semua program yang dapat dieksekusi harus menggunakan paket dengan nama main.

Tidak ada keharusan bahwa nama paket harus unik di antara semua paket-paket dalam membuat sebuah program, hanya saja nama import path haruslah unik.

Lihatlah dokumen Efektif Go untuk belajar lebih lanjut tentang konvensi penamaan pada Go.

Pengujian

Go memiliki framework (kerangka) pengujian yang ringan, terdiri dari perintah go test dan paket testing.

Pengujian dibuat dalam sebuah berkas yang berakhiran _test.go yang berisi fungsi-fungsi bernama TestXXX dengan format func TestXxx(t *testing.T). Kerangka tes menjalankan setiap fungsi TestXXX tersebut; Jika fungsi tes memanggil sebuah fungsi perintah kesalahan, seperti t.Error atau t.Fail, maka tes dianggap gagal.

Tambahkan sebuah tes ke paket stringutil dengan membuat berkas $GOPATH/src/github.com/user/stringutil/reverse_test.go yang berisi kode Go berikut.

package stringutil

import "testing"

func TestReverse(t *testing.T) {
	cases := []struct {
		in, want string
	}{
		{"Hello, world", "dlrow ,olleH"},
		{"Hello, 世界", "界世 ,olleH"},
		{"", ""},
	}
	for _, c := range cases {
		got := Reverse(c.in)
		if got != c.want {
			t.Errorf("Reverse(%q) == %q, want %q", c.in, got, c.want)
		}
	}
}

Kemudian jalankan tes dengan go test:

$ go test github.com/user/stringutil
ok  	github.com/user/stringutil 0.165s

Seperti biasa, jika menjalankan perintah go dari dalam direktori paket, kita bisa mengindahkan path dari paket:

$ go test
ok  	github.com/user/stringutil 0.165s

Jalankan go help test dan lihat dokumentasi dari paket testing untuk belajar lebih lanjut.

Paket eksternal

Sebuah import path mendeskripsikan bagaimana mendapatkan sumber kode dari paket menggunakan sebuah sistem kontrol revisi seperti Git atau Mercurial. Perkakas go menggunakan properti ini untuk secara otomatis mengambil paket dari repositori luar. Misalnya, contoh-contoh yang diuraikan dalam dokumen ini juga tersimpan di dalam sebuah repositori Git pada github.com/golang/example. Jika mengikutkan URL dari repositori pada import path, go get akan mengambil, membuat, dan memasangnya secara otomatis:

$ go get github.com/golang/example/hello
$ $GOPATH/bin/hello
Hello, Go examples!

Jika paket yang disebutkan tidak ada di dalam ruang-kerja, go get akan menyimpannya di dalam ruang-kerja pertama yang diset dalam GOPATH. (Jika paket sudah ada, go get akan melewatkan pengambilan dari luar dan berjalan seperti halnya go install.)

Setelah menjalankan perintah go get di atas, direktori ruang-kerja akan berbentuk seperti berikut:

bin/
    hello                           # program yang bisa dieksekusi
src/
    github.com/golang/example/
        .git/                       # metadata repositori Git
        hello/
            hello.go                # sumber program
        stringutil/
            reverse.go              # sumber paket
            reverse_test.go         # sumber tes
    github.com/user/
        hello/
            hello.go                # sumber program
        stringutil/
            reverse.go              # sumber paket
            reverse_test.go         # sumber tes

Program hello yang disimpan di Github bergantung pada paket stringutil pada repositori yang sama. Import path di dalam berkas hello.go menggunakan konvensi yang sama, sehingga perintah go get dapat menemukan dan memasang paket dependensi.

import "github.com/golang/example/stringutil"

Konvensi ini adalah cara mudah untuk membuat paket Go yang dapat digunakan oleh orang lain. Halaman Go Wiki dan situs godoc.org menyediakan daftar proyek dan paket eksternal dari Go.

Untuk informasi lebih lanjut tentang menggunakan repositori luar dengan perkakas go, lihatlah go help importpath.

Selanjutnya

Ikuti Tur Bahasa Go untuk belajar bahasa Go secara daring.