Dalam sebuah modul, kita mengumpulkan satu atau lebih paket untuk sekumpulan fungsi yang diskret dan berguna. Contohnya, kita bisa membuat sebuah modul untuk paket-paket yang memiliki fungsi-fungsi yang melakukan analisis finansial sehingga orang lain yang membuat aplikasi finansial dapat menggunakan karya kita.
Saat kita menambahkan atau memperbaiki fungsionalitas dalam modul, kita menerbitkan versi terbaru dari modul. Pengembang lain yang memanggil fungsi dalam modul kita dapat meng-impor paket-paket yang diperbarui dari modul kita dan mengujinya dengan versi yang terbaru sebelum menggunakan untuk production.
cd
mkdir greetings
cd greetings
go mod init example.com/greetings
Buat file greetings.go
package greetings
import "fmt"
// Hello mengembalikan sebuah salam untuk nama orang tertentu.
func Hello(name string) string {
// Kembalikan sebuah salam yang berisi `name` dalam sebuah pesan.
message := fmt.Sprintf("Hi, %v. Welcome!", name)
return message
}
Ini adalah kode pertama Anda dalam modul. Ia berisi sebuah fungsi Hello yang mengembalikan sebuah salam untuk setiap pemanggilan. Kita akan menulis kode yang memanggil fungsi tersebut di langkah selanjutnya.
Pada bagian sebelumnya, kita telah membuat sebuah modul “greetings”. Pada bagian ini, kita akan menulis kode, dalam bentuk aplikasi yang bisa dieksekusi, yang memanggil fungsi Hello dalam modul tersebut.
Buat sebuah direktori “hello” untuk sumber kode modul Go. Di direktori ini kita akan menulis kode yang memanggil modul sebelumnya.
Setelah membuat direktori tersebut, Anda seharusnya memiliki dua direktori: “hello” dan “greetings” dengan hirarki yang sama, seperti berikut:
/
|-- greetings/
|-- hello/
Misal anda masih berada di dalam di rektori greetings
cd ..
mkdir hello
cd hello
go mod init example.com/hello
Buat file baru bernama hello.go
package main
import (
"fmt"
"example.com/greetings"
)
func main() {
// Ambil pesan salaman dari fungsi Hello dan cetak ke layar.
message := greetings.Hello("Gladys")
fmt.Println(message)
}
Umumnya penggunaan dalam lingkungan production, Anda sebaiknya menerbitkan modul “example.com/greetings” pada sebuah repositori (dengan path modul yang merefleksikan lokasi diterbitkan), yang mana perkakas Go dapat temukan untuk mengunduhnya. Untuk sekarang, karena kita belum menerbitkan modul, kita harus mengadaptasi modul “example.com/hello” supaya dapat menemukan kode “example.com/greetings” dalam sistem berkas lokal Anda.
Sunting modul “example.com/hello” supaya menggunakan modul “example.com/greetings” yang ada di lokal Anda.
go mod edit --replace=example.com/greetings=../greetings
Perintah tersebut memberitahu supaya mengganti “example.com/greetings” dengan “../greetings” saat mencari lokasi dependensi. Setelah perintah dijalankan, berkas “go.mod” dalam direktori “hello” akan berisi sebuah direktif “replace”:
module example.com/hello
go 1.16
replace example.com/greetings => ../greetings
Lalu aktifkan dependency dengan perintah berikut :
go mod tidy
go: found example.com/greetings in example.com/greetings v0.0.0-00010101000000-000000000000
Setelah perintah selesai, berkas “go.mod” dalam modul “example.com/hello” akan berisi seperti berikut:
module example.com/hello
go 1.16
replace example.com/greetings => ../greetings
require example.com/greetings v0.0.0-00010101000000-000000000000
Perintah tersebut berfungsi untuk menemukan modul lokal dalam direktori “greetings”, kemudian menambahkan direktif require untuk menspesifikasikan bahwa “example.com/hello” membutuhkan “example.com/greetings”. Kita memakai dependensi ini saat kita mengimpor paket “greetings” dalam “hello.go”.
Angka setelah path modul adalah versi-palsu sebuah angka yang dibangkitkan sebagai pengganti dari angka versi semantik (yang belum gunakan oleh modul “greetings”).
Untuk mengarahkan ke modul yang telah diterbitkan, sebuah berkas go.mod tidak menggunakan direktif “replace” tapi hanya menggunkan direktif “require” dengan angka versi dibagian belakangnya.
require example.com/greetings v1.1.0
Jalankan kode
go run .
Hi, Gladys. Welcome!
Berikut cara membuat 2 modul dan memanggil salah satunya.
Penanganan eror adalah fitur penting pada kode yang solid. Pada bagian ini, kita akan menambahkan sedikit kode yang mengembalikan sebuah eror pada modul “greetings”, kemudian menangani-nya pada sisi pemanggil (modul “hello”).
Misal kembalikan error jika parameter name kosong, Ubah kode berikut pada greetings.go :
package greetings
import (
"errors"
"fmt"
)
// Hello mengembalikan sebuah salaman untuk nama seseorang.
func Hello(name string) (string, error) {
// Jika name kosong, kembalikan sebuah eror dengan pesan tertentu.
if name == "" {
return "", errors.New("empty name")
}
// Jika nama tidak kosong, kembalikan sebuah pesan salam yang menanam
// nama tersebut.
message := fmt.Sprintf("Hi, %v. Welcome!", name)
return message, nil
}
Berkut penjelasan baris kode di atas
Lalu buka file “hello/hello.go”, tangani kembalian eror dari fungsi Hello, berikut juga nilai yang tidak eror.
Salin kode berikut ke “hello.go”
package main
import (
"fmt"
"log"
"example.com/greetings"
)
func main() {
// Set properti dari Logger, termasuk prefiks dan flag untuk
// menon-aktifkan pencetakan waktu, sumber berkas, dan nomor baris.
log.SetPrefix("greetings: ")
log.SetFlags(0)
// Ambil pesan salam.
message, err := greetings.Hello("")
// Jika ada eror, cetak ke layar dan keluar dari program.
if err != nil {
log.Fatal(err)
}
// Jika tidak ada eror, cetak pesan yang dikembalikan ke layar.
fmt.Println(message)
}
Penjelasan :
Pada terminal, di dalam direktori “hello”, jalankan “hello.go” untuk memeriksa apakah kode berjalan dengan benar atau tidak.
Sekarang, karena kita mengirim nama yang kosong, kita akan mendapatkan sebuah eror.
go run .
greetings: empty name
exit status 1
Contoh penanganan error tersebut sangat umum dalam Go: Mengembalikan sebuah error sebagai nilai supaya pemanggil dapat memeriksanya.
Pada bagian ini, kita akan mengubah kode supaya tidak hanya mengembalikan satu bentuk salam saja, tetapi mengembalikan satu dari beberapa pesan salam yang telah ditentukan.
Untuk melakukan hal ini, kita akan menggunakan sebuah slice. Sebuah slice yaitu seperti sebuah array, namun ukurannya dapat berubah secara dinamis saat kita menambah atau menghapus item dalam slice. Slice adalah salah satu dari tipe yang sangat berguna pada Go.
Kita akan membuat slice berukuran kecil yang berisi tiga pesan salam, kemudian kita kembalikan salah satu dari pesan tersebut secara acak. Untuk informasi lebih lanjut tentang slice, lihat Go slice.
Dalam “greetings/greetings.go”, ubah kode kita supaya seperti di bawah.
package greetings
import (
"errors"
"fmt"
"math/rand"
"time"
)
// Hello returns a greeting for the named person.
func Hello(name string) (string, error) {
// If no name was given, return an error with a message.
if name == "" {
return name, errors.New("empty name")
}
// Create a message using a random format.
message := fmt.Sprintf(randomFormat(), name)
return message, nil
}
// init sets initial values for variables used in the function.
func init() {
rand.Seed(time.Now().UnixNano())
}
// randomFormat returns one of a set of greeting messages. The returned
// message is selected at random.
func randomFormat() string {
// A slice of message formats.
formats := []string{
"Hi, %v. Welcome!",
"Great to see you, %v!",
"Hail, %v! Well met!",
}
// Return a randomly selected message format by specifying
// a random index for the slice of formats.
return formats[rand.Intn(len(formats))]
}
Penjelasan :
Dalam “hello/hello.go”, ubah kode kita supaya seperti di bawah.
Kirim string “Glady” (atau nama apa pun yang Anda sukai) sebagai argumen dari fungsi Hello dalam hello.go.
package main
import (
"fmt"
"log"
"example.com/greetings"
)
func main() {
// Set properti dari Logger, termasuk prefiks dan flag untuk
// menon-aktifkan pencetakan waktu, sumber berkas, dan nomor baris.
log.SetPrefix("greetings: ")
log.SetFlags(0)
// Ambil pesan salam.
message, err := greetings.Hello("Gladys")
// Jika ada eror, cetak ke layar dan keluar dari program.
if err != nil {
log.Fatal(err)
}
// Jika tidak ada eror, cetak pesan yang dikembalikan ke layar.
fmt.Println(message)
}
Lalu jalankan kode beberapa kali, hasilnya akan berubah-ubah seperti di bawah ini :
$ go run .
Great to see you, Gladys!
$ go run .
Hi, Gladys. Welcome!
$ go run .
Hail, Gladys! Well met!
Pada bagian ini, kita akan menambah fungsionalitas pada modul “greetings” supaya dapat mengembalikan pesan salam untuk beberapa orang dalam satu pemanggilan. Dengan kata lain, kita akan menangani input dengan banyak nilai, kemudian memasangkan nilai input tersebut dengan nilai output. Untuk melakukan hal ini, kita akan mengirim sekumpulan nama ke sebuah fungsi yang dapat mengembalikan salam untuk setiap nama tersebut.
Mengubah parameter fungsi Hello dari satu nama menjadi beberapa nama akan mengubah signature dari fungsi tersebut. Jika Anda telah menerbitkan modul “example.com/greetings” sebelumnya dan user telah menulis kode yang telah memanggil Hello, perubahan tersebut akan membuat program mereka gagal dikompilasi.
Dalam situasi ini, pilihan yang terbaik yaitu membuat sebuah fungsi baru dengan nama yang berbeda. Fungsi yang baru tersebut akan menerima satu atau lebih nilai. Dengan ini kita menjaga fungsi yang lama demi menjaga kompatibilitas.
Dalam “greetings/greetings.go”, ubah lah kode Anda supaya seperti berikut :
package greetings
import (
"errors"
"fmt"
"math/rand"
"time"
)
// Hello mengembalikan sebuah salam untuk nama seseorang.
func Hello(name string) (string, error) {
// Jika nama kosong, kembalikan sebuah eror dengan pesan.
if name == "" {
return name, errors.New("empty name")
}
// Buat sebuah pesan salam dengan format acak.
message := fmt.Sprintf(randomFormat(), name)
return message, nil
}
// Hellos mengembalikan sebuah map yang mengasosiasikan setiap nama orang
// dengan sebuah pesan salam.
func Hellos(names []string) (map[string]string, error) {
// Sebuah map yang memetakan nama dengan pesan.
messages := make(map[string]string)
// Iterasi slice "names", panggil fungsi Hello untuk mendapatkan
// sebuah pesan untuk setiap nama.
for _, name := range names {
message, err := Hello(name)
if err != nil {
return nil, err
}
// Di dalam map, asosiasikan nama (kunci) dengan pesan (nilai).
messages[name] = message
}
return messages, nil
}
// init men-set pengacak angka.
func init() {
rand.Seed(time.Now().UnixNano())
}
// randomFormat mengembalikan sekumpulan pesan acak. Pesan yang dikembalikan
// dipilih secara acak.
func randomFormat() string {
// Slice dari sekumpulan format pesan.
formats := []string{
"Hi, %v. Welcome!",
"Great to see you, %v!",
"Hail, %v! Well met!",
}
// Kembalikan salah satu format pesan secara acak.
return formats[rand.Intn(len(formats))]
}
Penjelasan :
Dalam “hello.go”, ubah kode Anda menjadi seperti berikut :
package main
import (
"fmt"
"log"
"example.com/greetings"
)
func main() {
// Set properti dari Logger, termasuk prefiks dan opsi untuk mematikan
// pencetakan waktu, sumber berkas, dan nomor baris.
log.SetPrefix("greetings: ")
log.SetFlags(0)
// Sebuah slice yang berisi nama-nama.
names := []string{"Gladys", "Samantha", "Darrin"}
// Panggil fungsi Hellos untuk mendapatkan pesan salam untuk setiap nama.
messages, err := greetings.Hellos(names)
if err != nil {
log.Fatal(err)
}
// Jika tidak ada eror, cetak map yang diterima dari ke layar.
fmt.Println(messages)
}
Dalam perubahan ini, kita:
Pada terminal, pindah lah ke direktori yang menyimpan “hello/hello.go”, kemudian jalankan “go run” untuk memastikan kode bekerja dengan benar.
Keluaran dari perintah tersebut harusnya representasi dari nama dan pesan salam, kurang lebih seperti berikut:
go run .
map[Darrin:Hail, Darrin! Well met! Gladys:Hi, Gladys. Welcome! Samantha:Hail, Samantha! Well met!]
Pelajaran yang dapat diambil:
Sekarang setelah kode kita menjadi stabil, tambahkan sebuah Test. Menguji kode Anda selama pengembangan dapat menangkap bug yang mungkin terjadi saat perubahan dilakukan. Dalam topik ini, kita akan menambahkan sebuah Test untuk fungsi Hello.
Dukungan bawaan Go untuk unit tes membuat pengembang mudah membuat dan melakukan tes. Khususnya, dengan konvensi penamaan, paket “testing”, dan perintah “go test”, kita dapat dengan cepat menulis dan mengeksekusi tes.
Dalam direktori “greetings”, buatlah sebuah berkas bernama “greetings_test.go”
Dengan mengakhiri sebuah nama berkas dengan “_test.go” berarti memberitahu perintah “go test” bahwa berkas tersebut berisi fungsi-fungsi tes.
Dalam “greetings_test.go”, salin lah kode berikut ke dalam berkas dan simpan.
console.log( 'Code is Poetry' );