Pendahuluan

  • Go-Lang, selain merupakan bahasa pemrograman, Go-Lang juga menyediakan Standard Library (package bawaan) tanpa harus menggunakan package dari luar buatan orang lain
  • Contoh pada Kelas Golang Dasar, kita sudah belajar package bernama fmt atau errors
  • Selain package tersebut, sebenarnya masih banyak package lainnya yang bisa kita gunakan

Membuat Project

$ go mod init `standard-library`

Package fmt

souce:: https://pkg.go.dev/fmt

  • Sebelumnya kita sudah sering menggunakan package fmt dengan menggunakan function Println
  • Selain Println, masih banyak function yang terdapat di package fmt, contohnya banyak digunakan untuk melakukan format
package main
 
import "fmt"
 
func main() {
	firstName := "Rahmat"
	lastName := "Ardiansyah"
 
	fmt.Printf("Hello '%s %s'\n", firstName, lastName)
}
➜ go run fmt.go 
Hello 'Rahmat Ardiansyah'
 

Package errors

source:: https://pkg.go.dev/errors

  • Sebelumnya kita sudah membahas tentang interface error yang merupakan representasi dari error di Go-Lang, dan membuat error menggunakan function errors.New()
  • Masih banyak yang bisa kita lakukan menggunakan package errors, contohnya ketika kita ingin membuat beberapa value error yang berbeda
package main
 
import (
	"errors"
	"fmt"
)
 
var (
	ValidatorError = errors.New("validator error")
	NotFoundError  = errors.New("not found error")
)
 
func GetById(id string) error {
	if id == "" {
		return ValidatorError
	}
 
	if id != "rahmat" {
		return NotFoundError
	}
 
	return nil
}
 
func main() {
 
	err := GetById("rahmat")
 
	if err != nil {
		if errors.Is(err, ValidatorError) {
			fmt.Println("Validation Error")
		} else if errors.Is(err, NotFoundError) {
			fmt.Println("Not Found Error")
		} else {
			fmt.Println("Unknown Error")
		}
	}
 
}
learn/go/standard-library via 🐹 v1.25.4 
➜ go run error.go 
Validation Error
 
learn/go/standard-library via 🐹 v1.25.4 
➜ go run error.go 
 

Package os

source:: https://golang.org/pkg/os/

  • Go-Lang telah menyediakan banyak sekali package bawaan, salah satunya adalah package os
  • Package os berisikan fungsionalitas untuk mengakses fitur sistem operasi secara independen (bisa digunakan disemua sistem operasi)
package main
 
import (
	"fmt"
	"os"
)
 
func main() {
	args := os.Args
 
	fmt.Println(args)
}
➜ go run os.go 10 20 30
[/tmp/go-build3002110511/b001/exe/os 10 20 30]
  • os.Args untuk mengambil argument user saat menjalankan aplikasinya
package main
 
import (
	"fmt"
	"os"
)
 
func main() {
	hostname, error := os.Hostname()
 
	if error == nil {
		fmt.Println(hostname)
	} else {
		fmt.Println(error.Error())
	}
}
➜ go run os.go 
arch
  • os.Hostname() untuk mendapatkan nama hostname dari device yang digunakan

Function stat

source:: https://pkg.go.dev/os#Stat

  • Lstats mengembalikan sebuah FileInfo
  • Lstat juga mengembalikan sebuah error, jika erro akan mengembalikan PathError
package main
 
import (
	"errors"
	"fmt"
	"os"
)
 
func main() {
	logFile := "example.log"
 
	exist, err := fileExists(logFile)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
 
	fmt.Println("File exists:", exist)
}
 
func fileExists(path string) (bool, error) {
	_, err := os.Stat(path)
 
	switch {
	case err == nil:
		// file ditemukan
		return true, nil
 
	case errors.Is(err, os.ErrNotExist):
		// file tidak ditemukan
		return false, nil
 
	default:
		// error lain, misal permission denied
		return false, err
	}
}
  • Coding diatas digunakan untuk pengecekan apakah file tersebut ada atau tidak
  • Jika ada kembalikan true dan jika tidak kembalikan false

Function Lstat

source:: https://pkg.go.dev/os#Lstat

  • Lstats mengembalikan sebuah FileInfo
  • Jika file adalah sebuah symbolic link akan mengembalikan description itu symbolic link
  • Lstat juga mengembalikan sebuah error, akan mengembalikan PathError
package main
 
import (
	"errors"
	"fmt"
	"os"
)
 
func main() {
	path := "example.symlink"
 
	isLink, err := isSymlink(path)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
 
	fmt.Println("Is symbolic link:", isLink)
}
 
func isSymlink(path string) (bool, error) {
	info, err := os.Lstat(path)
	if err != nil {
		// Jika path tidak ada → bukan symlink, tapi bukan error kritis
		if errors.Is(err, os.ErrNotExist) {
			return false, nil
		}
 
		// Error lain → perlu di-handle caller
		return false, err
	}
 
	// Mengecek apakah file mode menunjukkan symlink
	return info.Mode()&os.ModeSymlink != 0, nil
}
 
  • Coding diatas untuk cek apakah file tersebut merupakan symbolic link?
  • jika iya kembalikan true, jika false kembalikan tidak

Function Create

source:: https://pkg.go.dev/os#Create

Create creates or truncates the named file. If the file already exists, it is truncated. If the file does not exist, it is created with mode 0o666 (before umask). If successful, methods on the returned File can be used for I/O; the associated file descriptor has mode O_RDWR. The directory containing the file must already exist. If there is an error, it will be of type *PathError.

  • Function create berfungsi untuk membuat file
  • Jika file sudah ada akan menimpa file tersebut
  • Jika belum ada maka akan membuat file dan permissionnya 666
  • Jika sukses kita bisa menggunakan method dari IO
  • Saat membuat file, directorynya sudah harus ada sebelumnya
  • function create juga mengembalikan error
package main
 
import (
	"errors"
	"fmt"
	"os"
)
 
func main() {
	newPath := "new/file.txt"
	fmt.Println("file created", createFile(newPath))
}
 
func createFile(path string) error {
	file, err := os.Create(path)
	if err != nil {
		return err
	}
 
	defer file.Close()
	return nil
}
➜ go run create_file.go
File exists: true
Is symbolic link: true
file created open neww/file.txt: no such file or directory
 
➜ go run create_file.go
File exists: true
Is symbolic link: true
file created open new/file.txt: permission denied
 
➜ go run create_file.go
File exists: true
Is symbolic link: true
file created <nil>
 
➜ go run create_file.go
File exists: true
Is symbolic link: true
file created <nil>
  • Coding diatas bertujuan untuk membuat file di dalam folder new/ bernama file.txt
  • Jika folder belum ada maka akan mengembalikan error no such file or directory
  • JIka sudah ada tapi permission nya tidak boleh menulis akan mengembalikan error permission denied
  • Jika folder sudah ada dan permission bisa menulis maka file tersebut akan dibuat
  • Jika file sudah ada dan menjalankan kode kembali maka akan menimpa file sebelumnya atau disebut truncation

Catatan

  • Ketika membuka file di golang akan mengkonsumsi resource seperti memory dan file descriptor
  • Jika kita tidak menutup file tersebut akan terus memakan resource dan terjadi memory leak

File Descriptor

File descriptor di Go adalah nomor integer unik yang digunakan sistem operasi untuk mengidentifikasi file atau sumber daya I/O (Input/Output) yang terbuka oleh sebuah program,

Function Mkdir & MkdirAll

source::

  • https://pkg.go.dev/os#Root.MkdirAll

  • https://pkg.go.dev/os#Root.Mkdir

  • Mkdir & MkdirAll digunakan untuk membuat folder

  • Menerima 2 argument, yaitu path (string) dan permission (FileMode)

  • Mkdir & MkdirAll akan return nil atau error

  • Jika folder belum ada atau sudah ada sebelumnya maka akan return nil (tidak error)

  • Perbedaan Mkdir & MkdirAll:

    • Mkdir hanya membuat 1 folder saja, tidak bisa os.Mkdir("a/b/c", 0755)
    • MkdirAll bisa membuat banyak folder termasuk subfolder os.MkdirAll("a/b/c", 0755)
package main
 
import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
)
 
func main() {
	newPath := "new/file.txt"
 
	if err := createFile(newPath); err != nil {
		fmt.Println("Error:", err)
		return
	}
 
	fmt.Println("File created successfully")
}
 
func createFile(path string) error {
	// Pastikan direktori tujuan sudah ada
	dir := filepath.Dir(path)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("failed creating directory: %w", err)
	}
 
	// Buat file baru (overwrite jika sudah ada)
	f, err := os.Create(path)
	if err != nil {
		return fmt.Errorf("failed creating file: %w", err)
	}
	defer f.Close()
 
	return nil
}
  • coding diatas membuat file beserta folder dan subfoldernya jika belum ada (menggunakan MkdirAll)

Function Open & OpenFile

  • Open & OpenFile fungsi pembuka file yang paling fleksibel
  • Open hanya bisa read-only sedangkan OpenFile (flag):
    • Baca saja
    • Tulis saja
    • Baca dan tulis
    • Append atau menambah baris baru
    • Hapus isinya atau truncation
    • dan lainnya
  • OpenFile menerima 3 argument
FlagFungsi
O_RDONLYBuka file untuk baca
O_WRONLYBuka file untuk tulis
O_RDWRBuka file untuk baca + tulis
O_APPENDTulis selalu di akhir
O_CREATEBuat file kalau belum ada
O_EXCLError jika file sudah ada (harus dengan O_CREATE)
O_TRUNCKosongkan isi file
O_SYNCTulis sinkron ke storage
O_DSYNCSinkron data saja
O_NOCTTYJangan jadikan terminal sebagai controlling terminal
O_NONBLOCKBuka file non-blocking
package main
 
import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
)
 
func main() {
	newPath := "folder/file.txt"
	fmt.Println(createFileIfNotExist(newPath))
}
 
func createFileIfNotExist(path string) error {
	file, err := os.OpenFile(path, os.O_RDWR|os.O_EXCL|os.O_CREATE, 0755)
 
	if err != nil {
		return err
	}
 
	defer file.Close()
	return nil
 
}
  • Koding diatas untuk membuat file.txt
  • Jika folder folder belum ada maka akan mengembalikan open folder/file.txt: no such file or directory
  • Jika folder folder sudah ada maka akan berhasil membuat file
  • Jika folder dan file sudah ada maka akan mengembalikan open folder/file.txt: file exists

Function Write & WriteFile

source:: https://pkg.go.dev/os#WriteFile

  • Write & WriteFile berfungsi untuk menulis text ke dalam file
  • WriteFile berbeda dengan Write, karena WriteFile akan menimpa isi dari konten sebelumnya dengan yang baru
  • WriteFile menerima 3 argument:
  • WriteFile Mengembalikan error, misalnya jika permission file read-only
package main
import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
)
func main() {
	newPath := "folder/file.txt"
	fmt.Println("file created", createFile(newPath))
	fmt.Println(createFileIfNotExist(newPath))
	fmt.Println("Write file", writeFile(newPath, []byte("Hello World")))
}
 
func createFile(path string) error {
	// Pastikan direktori tujuan sudah ada
	dir := filepath.Dir(path)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("failed creating directory: %w", err)
	}
	file, err := os.Create(path)
	if err != nil {
		return err
	}
	defer file.Close()
	return nil
}
 
func createFileIfNotExist(path string) error {
	file, err := os.OpenFile(path, os.O_RDWR|os.O_EXCL|os.O_CREATE, 0755)
	if err != nil {
		return err
	}
	defer file.Close()
	return nil
}
 
func writeFile(path string, data []byte) error {
	return os.WriteFile(path, data, 0644)
}
➜ go run write_file.go
file created <nil>
open folder/file.txt: file exists
Write file <nil>
  • Koding diatas untuk membuat menulis file di folder/file.txt yang berisi Hello World
  • Jika permission file tidak bisa write akan error: Write file open folder/file.txt: permission denied

Beriku adalah contoh koding untuk write:

package main
 
import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
)
 
func main() {
	newPath := "folder/file.txt"
	fmt.Println("file created", createFile(newPath))
 
	fmt.Println(createFileIfNotExist(newPath))
 
	fmt.Println("Write file", writeFile(newPath, []byte("Hello World\n")))
	fmt.Println("Append file", appendFile(newPath, []byte("Create New Line")))
 
}
 
func createFile(path string) error {
	// Pastikan direktori tujuan sudah ada
	dir := filepath.Dir(path)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("failed creating directory: %w", err)
	}
 
	file, err := os.Create(path)
	if err != nil {
		return err
	}
 
	defer file.Close()
	return nil
}
 
func createFileIfNotExist(path string) error {
	file, err := os.OpenFile(path, os.O_RDWR|os.O_EXCL|os.O_CREATE, 0755)
 
	if err != nil {
		return err
	}
 
	defer file.Close()
	return nil
 
}
 
func writeFile(path string, data []byte) error {
	return os.WriteFile(path, data, 0644)
}
 
func appendFile(path string, data []byte) error {
	file, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND, 0755)
	if err != nil {
		return err
	}
 
	defer file.Close()
 
	_, err = file.Write(data)
 
	return err
}
  • appendFile berfungsi untuk menambahakan baris ke file yang sudah ada sebelumnya (tidak menimpannya)

Function ReadFile

  • ReadFile digunakan untuk membaca sebuah file
  • ReadFile menerima 1 buah argument:
    • name string
  • Mengembalikan 2 buah value, yaitu []byte dan error
package main
 
import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
)
 
func main() {
	newPath := "folder/file.txt"
	fmt.Println("file created", createFile(newPath))
 
	fmt.Println(createFileIfNotExist(newPath))
 
	fmt.Println("Write file", writeFile(newPath, []byte("Hello World\n")))
	fmt.Println("Append file", appendFile(newPath, []byte("Create New Line")))
 
	data, _ := readFile(newPath)
 
	fmt.Println("Read file", string(data))
 
}
 
 
func createFile(path string) error {
	// Pastikan direktori tujuan sudah ada
	dir := filepath.Dir(path)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("failed creating directory: %w", err)
	}
 
	file, err := os.Create(path)
	if err != nil {
		return err
	}
 
	defer file.Close()
	return nil
}
 
func createFileIfNotExist(path string) error {
	file, err := os.OpenFile(path, os.O_RDWR|os.O_EXCL|os.O_CREATE, 0755)
 
	if err != nil {
		return err
	}
 
	defer file.Close()
	return nil
 
}
 
func writeFile(path string, data []byte) error {
	return os.WriteFile(path, data, 0644)
}
 
func appendFile(path string, data []byte) error {
	file, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND, 0755)
	if err != nil {
		return err
	}
 
	defer file.Close()
 
	_, err = file.Write(data)
 
	return err
}
 
func readFile(path string) ([]byte, error) {
	return os.ReadFile(path)
}
  • Koding diatas bertujuan untuk readFile dari argument newFile dan di convert dari byte ke string

Function Remove & RemoveAll

  • function Remove & RemoveAll digunakan untuk menghapus file atau folder
  • Perbedaannya jika menghapus folder menggunakan Remove tidak bisa jika folder tersebut ada isinya, tapi bisa menggunakan RemoveAll
  • keduanya menerima 1 argument:
    • name string
  • dan mengembalikan error, misalnya jika permission write tidak ada
package main
 
import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
)
 
func main() {
	fmt.Println("Delete file", deleteFile(("foldernih")))
}
 
func deleteFile(path string) error {
	return os.Remove(path)
	// return os.RemoveAll(path) // atau
}
  • RemoveAll akan menghapus file atau folder(beserta isinya)

function Stats dan Lstats

  • kedua function untuk mendapatkan info dari file atau folder seperti size, modified time dan lainnya
  • Menerima 1 argumen:
    • name string
  • mengembalikan struct FileInfo dan error
package main
 
import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"time"
)
 
func main() {
	newPath := "folder/file.txt"
	fmt.Println("file created", createFile(newPath))
 
	fmt.Println(createFileIfNotExist(newPath))
 
	fmt.Println("Write file", writeFile(newPath, []byte("Hello World\n")))
	fmt.Println("Append file", appendFile(newPath, []byte("Create New Line")))
 
	data, _ := readFile(newPath)
 
	fmt.Println("Read file", string(data))
	fmt.Println("Delete file", deleteFile(("foldernih")))
 
	size, modTime, _ := fileStats(newPath)
	fmt.Println("File size", size)
	fmt.Println("File modified", modTime)
 
}
 
func createFile(path string) error {
	// Pastikan direktori tujuan sudah ada
	dir := filepath.Dir(path)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return fmt.Errorf("failed creating directory: %w", err)
	}
 
	file, err := os.Create(path)
	if err != nil {
		return err
	}
 
	defer file.Close()
	return nil
}
 
func createFileIfNotExist(path string) error {
	file, err := os.OpenFile(path, os.O_RDWR|os.O_EXCL|os.O_CREATE, 0755)
 
	if err != nil {
		return err
	}
 
	defer file.Close()
	return nil
 
}
 
func writeFile(path string, data []byte) error {
	return os.WriteFile(path, data, 0644)
}
 
func appendFile(path string, data []byte) error {
	file, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND, 0755)
	if err != nil {
		return err
	}
 
	defer file.Close()
 
	_, err = file.Write(data)
 
	return err
}
 
func readFile(path string) ([]byte, error) {
	return os.ReadFile(path)
}
 
func deleteFile(path string) error {
	return os.Remove(path)
}
 
func fileStats(path string) (int64, time.Time, error) {
	info, err := os.Stat(path)
	if err != nil {
		return -1, time.Time{}, err
	}
 
	size := info.Size()
	modTime := info.ModTime()
	return size, modTime, nil
}
  • function fileStats digunakan untuk mendapatkan size dan modified time

Function ReadDir

  • function ReadDir digunakan untuk melihat daftar files atau folder di directory tertentu
  • Menerima 1 argument:
    • name string
  • mengembalikan []DirEntry dan error: https://pkg.go.dev/os#DirEntry
package main
 
import (
	"fmt"
	"io"
	"io/fs"
	"os"
)
 
func main() {
	newPath := "folder/file.txt"
	copiedPath := "folder/copy.txt"
	fmt.Println("Copy file", copyFile(newPath, copiedPath))
 
	listedFiles, _ := listDir("./")
	fmt.Println("", listedFiles)
 
}
 
func copyFile(srcPath, destPath string) error {
	src, err := os.Open(srcPath)
	if err != nil {
		return err
	}
 
	defer src.Close()
 
	dest, err := os.Create(destPath)
	if err != nil {
		return err
	}
	defer dest.Close()
 
	_, err = io.Copy(dest, src)
 
	if err != nil {
		return err
	}
 
	return dest.Sync()
 
}
 
func listDir(path string) ([]fs.DirEntry, error) {
	entries, err := os.ReadDir(path)
	if err != nil {
		return nil, err
	}
 
	listedFiles := make([]fs.DirEntry, 0)
	for _, entry := range entries {
		// kembalikan files, bukan folder
		if !entry.IsDir() {
			listedFiles = append(listedFiles, entry)
		}
	}
 
	return listedFiles, nil
 
}
  • tambahkan validasi jika ingin mengembalikan files saja, bukan folder

Package flag

source:: https://golang.org/pkg/flag/

  • Package flag berisikan fungsionalitas untuk mem-parsing command line argument
package main
 
import (
	"flag"
	"fmt"
)
 
func main() {
	var username *string = flag.String("username", "root", "database username")
	var password *string = flag.String("password", "root", "database password")
	var host *string = flag.String("host", "localhost", "database host")
	var port *int = flag.Int("port", 0, "database port")
 
	flag.Parse() // WAJIB di parse terlebih dahulu
 
	fmt.Println("Username:", *username)
	fmt.Println("Password:", *password)
	fmt.Println("Host:", *host)
	fmt.Println("Port:", *port)
}
learn/go/standard-library via 🐹 v1.25.4 
➜ go run flag.go 
Username: root
Password: root
Host: localhost
Port: 0
 
learn/go/standard-library via 🐹 v1.25.4 
➜ go run flag.go -username=rahmat -password=12321 -host=121.2.3.12 -port=8080
Username: rahmat
Password: 12321
Host: 121.2.3.12
Port: 8080
  • Jika tidak ada argument yang dikirim maka akan mengembalikan default valuenya

Parse Flag

Flag harus di parse terlebih dahulu

Flag.NewFlagSet

  • flag.NewFlagSet digunakan untuk membuat kumpulan flag khusus (FlagSet) yang terpisah dari flag default. Ini sangat penting saat kita membuat subcommand, seperti:
myapp serve --port=3000
myapp build --minify
flag.NewFlagSet(name string, errorHandling flag.ErrorHandling) *flag.FlagSet

Parameter:

  1. name Nama dari subcommand / flagset (contoh: "serve", "build").
  2. errorHandling Bagaimana FlagSet menangani error parsing:
    • flag.ExitOnError → keluar program bila ada error
    • flag.PanicOnError → panic
    • flag.ContinueOnError → error dikembalikan ke caller

Contoh kasus:

package main
 
import (
	"flag"
	"fmt"
	"os"
)
 
func main() {
	if len(os.Args) < 2 {
		fmt.Println("Commands:")
		fmt.Println("  build    Build the site")
		fmt.Println("  serve    Serve the site with hot reload")
		os.Exit(1)
	}
 
	command := os.Args[1]
 
	serveCmd := flag.NewFlagSet("serve", flag.ExitOnError)
	servePort := serveCmd.Int("port", 3001, "application port")
	dirContent := serveCmd.String("dir", "content", "directory content")
 
	switch command {
	case "serve", "server":
		serveCmd.Parse(os.Args[2:])
 
		fmt.Printf("Serving at http://localhost:%d\n", *servePort)
		fmt.Println("Content dir:", *dirContent)
 
	case "build":
		serveCmd.Parse(os.Args[2:])
		fmt.Println("Content dir:", *dirContent)
 
	default:
		fmt.Println("Unknown command:", command)
	}
}

Package strings

source:: https://golang.org/pkg/strings/

  • Package strings adalah package yang berisikan function-function untuk memanipulasi tipe data String

Function di Package strings

FunctionKegunaan
strings.Trim(string, cutset)Memotong cutset di awal dan akhir string
strings.ToLower(string)Membuat semua karakter string menjadi lower case
strings.ToUpper(string)Membuat semua karakter string menjadi upper case
strings.Split(string, separator)Memotong string berdasarkan separator
strings.Contains(string, search)Mengecek apakah string mengandung string lain
strings.ReplaceAll(string, from, to)Mengubah semua string dari from ke to
package main
 
import (
	"fmt"
	"strings"
)
 
func main() {
	fmt.Println(strings.Contains("Rahmat", "mat"))
	fmt.Println(strings.Split("Rahmat Ardiansyah", " "))
	fmt.Println(strings.ToLower("Rahmat Ardiansyah"))
	fmt.Println(strings.ToUpper("Rahmat Ardiansyah"))
	fmt.Println(strings.Trim("   Rahmat Ardiansyah   ", " "))
	fmt.Println(strings.Replace("mat Ardiansyah", "mat", "Rahmat", 1))
}
➜ go run strings.go 
true
[Rahmat Ardiansyah]
rahmat ardiansyah
RAHMAT ARDIANSYAH
Rahmat Ardiansyah
Rahmat Ardiansyah

Package strconv

source:: https://golang.org/pkg/strconv/

  • Sebelumnya kita sudah belajar cara konversi tipe data, misal dari int32 ke int64
  • Bagaimana jika kita butuh melakukan konversi yang tipe datanya berbeda? Misal dari int ke string, atau sebaliknya
  • Hal tersebut bisa kita lakukan dengan bantuan package strconv (string conversion)

Function di Package strconv

FunctionKegunaan
strconv.parseBool(string)Mengubah string ke bool
strconv.parseFloat(string)Mengubah string ke float
strconv.parseInt(string)Mengubah string ke int64
strconv.FormatBool(bool)Mengubah bool ke string
strconv.FormatFloat(float, … )Mengubah float64 ke string
strconv.FormatInt(int, … )Mengubah int64 ke string
package main
 
import (
	"fmt"
	"strconv"
)
 
func main() {
	b, err := strconv.ParseBool("false")
	if err != nil {
		fmt.Println(err.Error())
	} else {
		fmt.Println(b)
	}
}
learn/go/standard-library via 🐹 v1.25.4 
➜ go run strconv.go 
strconv.ParseBool: parsing "SALAH": invalid syntax
 
learn/go/standard-library via 🐹 v1.25.4 
➜ go run strconv.go 
false
package main
 
import (
	"fmt"
	"strconv"
)
 
func main() {
	binary := strconv.FormatInt(999, 2)
 
	fmt.Println(binary) // 1111100111
}

Package math

source:: https://golang.org/pkg/math/

  • Package math merupakan package yang berisikan constant dan fungsi matematika

Function di Package math

FunctionKegunaan
math.Round(float64)Membulatkan float64 keatas atau kebawah, sesuai dengan yang paling dekat
math.Floor(float64)Membulatkan float64 kebawah
math.Ceil(float64)Membulatkan float64 keatas
math.Max(float64, float64)Mengembalikan nilai float64 paling besar
math.Min(float64, float64)Mengembalikan nilai float64 paling kecil
package main
 
import (
	"fmt"
	"math"
)
 
func main() {
	fmt.Println(math.Ceil(1.40))
	fmt.Println(math.Floor(1.40))
	fmt.Println(math.Round(1.40))
	fmt.Println(math.Max(1, 2))
	fmt.Println(math.Min(1, 2))
}

Package container/list

source:: https://golang.org/pkg/container/list/

  • Package container/list adalah implementasi struktur data double linked list di Go-Lang
  • Digunakan biasanya untuk atrian atau tumpukan

package main
 
import (
	"container/list"
	"fmt"
)
 
func main() {
	var data *list.List = list.New()
 
	data.PushBack("Rahmat")
	data.PushBack("Ardiansyah")
	data.PushBack("24")
 
	var head *list.Element = data.Front()
	fmt.Println(head.Value)               // Rahmat
	fmt.Println(head.Next().Value)        // Ardiansyah
	fmt.Println(head.Next().Next().Value) // 24
 
	fmt.Println("FOR LOOP")
	for el := data.Front(); el != nil; el = el.Next() {
		fmt.Println(el.Value)
	}
}
➜ go run double_link_list.go 
Rahmat
Ardiansyah
24
FOR LOOP
Rahmat
Ardiansyah
24

Package container/ring

source:: https://golang.org/pkg/container/ring/

  • Package container/ring adalah implementasi struktur data circular list
  • Circular list adalah struktur data ring, dimana diakhir element akan kembali ke element awal (HEAD)

package main
 
import (
	"container/ring"
	"fmt"
	"strconv"
)
 
func main() {
	var data *ring.Ring = ring.New(5)
 
	// data.Value = "Value 1"
	// data.Next().Value = "Value 2"
	// data.Next().Next().Value = "Value 3"
	// data.Next().Next().Next().Value = "Value 4"
	// data.Next().Next().Next().Next().Value = "Value 5"
 
	// data.Value = "Value 1"
 
	// data = data.Next()
	// data.Value = "Value 2"
 
	// data = data.Next()
	// data.Value = "Value 3"
 
	// data = data.Next()
	// data.Value = "Value 4"
 
	// data = data.Next()
	// data.Value = "Value 5"
 
	for i := 0; i < data.Len(); i++ {
		data.Value = "Value " + strconv.Itoa(i)
		data = data.Next()
	}
 
	data.Do(func(value any) {
		fmt.Println(value)
	})
}

Package sort

source:: https://golang.org/pkg/sort/

  • Package sort adalah package yang berisikan utilitas untuk proses pengurutan
  • Agar data kita bisa diurutkan, kita harus mengimplementasikan kontrak di interface sort.Interface
package main
 
import (
	"fmt"
	"sort"
)
 
type User struct {
	Name string
	Age  int
}
 
type UserSlice []User
 
func (s UserSlice) Len() int {
	return len(s)
}
 
func (s UserSlice) Less(i, j int) bool {
	return s[i].Age < s[j].Age
}
 
func (s UserSlice) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}
 
func main() {
	users := []User{
		{"Rahmat", 24},
		{"Budi", 35},
		{"Joko", 30},
		{"Adit", 20},
	}
 
	sort.Sort(UserSlice(users))
 
	fmt.Println(users)
}

Package time

source:: https://golang.org/pkg/time/

  • Package time adalah package yang berisikan fungsionalitas untuk management waktu di Go-Lang

Function di Package time

FunctionKegunaan
time.Now()Untuk mendapatkan waktu saat ini
time.Date(…)Untuk membuat waktu
time.Parse(layout, string)Untuk memparsing waktu dari string
package main
 
import (
	"fmt"
	"time"
)
 
func main() {
	now := time.Now()
 
	fmt.Println(now)
 
	var utc time.Time = time.Date(2009, time.August, 17, 0, 0, 0, 0, time.UTC)
 
	fmt.Println(utc)
	fmt.Println(utc.Local())
 
	formatter := "2006-01-02 15:04:05"
 
	value := "2020-10-10 10:10:10"
 
	valueTime, error := time.Parse(formatter, value)
 
	if error != nil {
		fmt.Println(error.Error())
	} else {
		fmt.Println(valueTime)
	}
}
2025-12-02 13:47:28.608221591 +0700 WIB m=+0.000011804
2009-08-17 00:00:00 +0000 UTC
2009-08-17 07:00:00 +0700 WIB
2020-10-10 10:10:10 +0000 UTC

Duration

  • Saat menggunakan tipe data waktu, kadang kita butuh data berupa durasi
  • Package tipe memiliki type Duration, yang sebenarnya adalah alias untuk int64
  • Namun terdapat banyak method yang bisa kita gunakan untuk memanipulasi Duration
  • Biasanya digunakan untuk mengasih timeout seperti connect ke database
package main
 
import (
	"fmt"
	"time"
)
 
func main() {
	var duration1 time.Duration = 100 * time.Second
	var duration2 time.Duration = 10 * time.Millisecond
	var duration3 time.Duration = duration1 - duration2
 
	fmt.Println(duration3)
}

Package reflect

source:: https://golang.org/pkg/reflect/

  • Dalam bahasa pemrograman, biasanya ada fitur Reflection, dimana kita bisa melihat struktur kode kita pada saat aplikasi sedang berjalan
  • Hal ini bisa dilakukan di Go-Lang dengan menggunakan package reflect
  • Reflection sangat berguna ketika kita ingin membuat library yang general sehingga mudah digunakan
package main
 
import (
	"fmt"
	"reflect"
)
 
type Sample struct {
	Name string
}
 
type Person struct {
	Name, Address string
	Age           int
}
 
func readField(value any) {
	var valueType reflect.Type = reflect.TypeOf(value)
 
	fmt.Println("Type Name", valueType.Name())
 
	for i := 0; i < valueType.NumField(); i++ {
		var valueType reflect.StructField = valueType.Field(i)
		fmt.Println(valueType.Name)
		fmt.Println(valueType.Type)
	}
 
}
 
func main() {
	readField(Sample{"Rahmat"})
	readField(Person{"Rahmat", "Riau", 24})
}
➜ go run reflect.go 
Type Name Sample
Name
string
Type Name Person
Name
string
Address
string
Age
int
package main
 
import (
	"fmt"
	"reflect"
)
 
type Sample struct {
	Name string `required:"true" max:"10"`
}
 
type Person struct {
	Name    string `required:"true" max:"10"`
	Address string `required:"true" max:"30"`
	Age     int    `required:"true" max:"100"`
}
 
func isValid(value any) (result bool) {
	t := reflect.TypeOf(value)
	for i := 0; i < t.NumField(); i++ {
		var structField reflect.StructField = t.Field(i)
 
		if structField.Tag.Get("required") == "true" {
			data := reflect.ValueOf(value).Field(i).Interface()
			result = data != ""
			if result == false {
				return result
			}
		}
 
	}
	return result
}
 
func main() {
	person := Person{"Rahmat", "", 24}
 
	fmt.Println(isValid(person))
}
➜ go run reflect.go 
false

Package regexp

source:: https://golang.org/pkg/regexp/

  • Package regexp adalah utilitas di Go-Lang untuk melakukan pencarian regular expression
  • Regular expression di Go-Lang menggunakan library C yang dibuat Google bernama RE2
  • https://github.com/google/re2/wiki/Syntax

Function di Package regexp

FunctionKegunaan
regexp.MustCompile(string)Membuat Regexp
Regexp.MatchString(string) boolMengecek apakah Regexp match dengan string
Regexp.FindAllString(string, max)Mencari string yang match dengan maximum jumlah hasil
package main
 
import (
	"fmt"
	"regexp"
)
 
func main() {
	var regex *regexp.Regexp = regexp.MustCompile(`m([a-z])t`)
 
	fmt.Println(regex.MatchString("mat"))
	fmt.Println(regex.MatchString("met"))
	fmt.Println(regex.MatchString("mAt"))
}
➜ go run regex.go 
true
true
false
package main
 
import (
	"fmt"
	"regexp"
)
 
func main() {
	var regex *regexp.Regexp = regexp.MustCompile(`m([a-z])t`)
	fmt.Println(regex.FindAllString("mat met mut tam", 4))
}
➜ go run regex.go
[mat met mut]

Package encoding

source:: https://pkg.go.dev/encoding

  • Golang menyediakan package encoding untuk melakukan encode dan decode
  • Golang menyediakan berbagai macam algoritma untuk encoding, contoh yang populer adalah base64, csv dan json

base64

package main
 
import (
	"encoding/base64"
	"fmt"
)
 
func main() {
	value := "Rahmat Ardiansyah"
 
	encoded := base64.StdEncoding.EncodeToString([]byte(value))
 
	fmt.Println("Encoded", encoded)
 
	decoded, error := base64.StdEncoding.DecodeString(encoded)
 
	if error != nil {
		fmt.Println(error.Error())
	} else {
		fmt.Println("Decoded", string(decoded))
	}
}

CSV Reader

package main
 
import (
	"encoding/csv"
	"fmt"
	"io"
	"strings"
)
 
func main() {
	csvString := "Rahmat, Ardiansyah, 24\n" +
		"Budi, Pratama, 30\n" +
		"Joko, morro, diah, 40"
 
	reader := csv.NewReader(strings.NewReader(csvString))
 
	for {
		record, error := reader.Read()
		if error == io.EOF {
			break
		}
		fmt.Println(record)
	}
}

CSV Writer

package main
 
import (
	"encoding/csv"
	"os"
)
 
func main() {
	writer := csv.NewWriter(os.Stdout)
	_ = writer.Write([]string{"Rahmat", "Ardiansyah", "24"})
	_ = writer.Write([]string{"Budi", "Pratama", "30"})
	_ = writer.Write([]string{"Joko", "Morro", "34"})
	writer.Flush()
}

Package slices

source:: https://pkg.go.dev/slices

  • Di Golang versi terbaru, terdapat fitur bernama Generic, fitur Generic ini membuat kita bisa membuat parameter dengan tipe yang bisa berubah-ubah, tanpa harus menggunakan interface kosong / any
  • Salah satu package yang menggunakan fitur Generic ini adalah package slices
  • Package slices ini digunakan untuk memanipulasi data di slice
package main
 
import (
	"fmt"
	"slices"
)
 
func main() {
	names := []string{"Jhon", "Paul", "George", "Ringo"}
	fmt.Println(slices.Max(names))
	fmt.Println(slices.Min(names))
	fmt.Println(slices.Contains(names, "Paul"))
	fmt.Println(slices.Index(names, "Paul"))
	fmt.Println(slices.Index(names, "Mat"))
 
	values := []int{100, 80, 90, 95}
	fmt.Println(slices.Max(values))
	fmt.Println(slices.Min(values))
}

log

fmt dan log sama-sama bisa menampilkan teks ke output, tetapi keduanya dibuat untuk tujuan yang berbeda. Perbedaannya cukup penting, terutama dalam aplikasi besar.

  • fmt Dipakai untuk formatted printing (mencetak teks biasa). Cocok untuk output umum, debugging ringan, atau tampilan CLI.
  • log Dipakai untuk structured application logging, dengan fitur tambahan yang membantu debugging dan error tracking.

log mendukung:

  • Timestamp otomatis
  • Level logging (walau versi default Go hanya Print / Fatal / Panic)
  • Menulis ke file, buffer, atau writer lain menggunakan SetOutput

Bisa diarahkan ke file log

log bisa menulis ke file, bukan console:

file, _ := os.Create("app.log")
log.SetOutput(file)
log.Println("Server started")

fmt tidak mendukung ini (harus manual menggunakan fmt.Fprintln(file, ...)).

Use-case terbaik

KebutuhanGunakan
Cetak output biasa untuk userfmt
Debug cepat, print nilaifmt
Logging aplikasi (server, CLI, engine)log
Output error yang seriuslog.Fatal / log.Panic
Menyimpan log ke filelog
Pipeline command (stdout/stderr separation)log
  • fmt

    • Dipakai untuk mencetak teks biasa
    • Tanpa timestamp
    • Tidak menandai level error
    • Output ke stdout
  • log

    • Dipakai untuk logging aplikasi
    • Ada timestamp + format khusus
    • Bisa fatal/panic
    • Output ke stderr
    • Bisa diarahkan ke file/other writer

Package path

source::

  • https://pkg.go.dev/path

  • https://pkg.go.dev/path/filepath

  • Package path digunakan untuk memanipulasi data path seperti path di URL atau path di File System

  • Secara default Package path menggunakan slash sebagai karakter path nya, oleh karena itu cocok untuk data URL

  • Namun jika ingin menggunakan untuk memanipulasi path di File System, karena Windows menggunakan backslash, maka khusus untuk File System, perlu menggunakan package path/filepath

package main
 
import (
	"fmt"
	"path"
)
 
func main() {
	fmt.Println(path.Dir("hello/world.go"))
	fmt.Println(path.Base("hello/world.go"))
	fmt.Println(path.Ext("hello/world.go"))
	fmt.Println(path.Join("hello/world/main.go"))
}
➜ go run path.go 
hello
world.go
.go
hello/world/main.go
package main
 
import (
	"fmt"
	"path/filepath"
)
 
func main() {
	fmt.Println(filepath.Dir("hello/world.go"))
	fmt.Println(filepath.Base("hello/world.go"))
	fmt.Println(filepath.Ext("hello/world.go"))
	fmt.Println(filepath.Join("hello/world/main.go"))
}
➜ go run filepath.go 
hello
world.go
.go
hello/world/main.go

Filepath.WalkDir

Fungsi filepath.WalkDir (atau filepath.Walk) adalah untuk melintasi (traverse) seluruh isi sebuah direktori secara rekursif, termasuk semua subdirektori dan filenya, untuk memproses setiap file dan folder yang ditemukan menggunakan fungsi callback yang disediakan, sangat berguna untuk mencari, menyalin, menghapus, atau memanipulasi file dalam jumlah besar di sebuah pohon direktori.

package content
 
import (
	"fmt"
	"geode/internal/config"
	"io/fs"
	"log"
	"path/filepath"
	"strings"
)
 
type FileEntry struct {
	Path         string
	RelativePath string
	Size         int64
	IsMarkdown   bool
	IsAsset      bool
}
 
func GetAllMarkdownFilesAndAssets(srcDir string) []FileEntry {
	var entries []FileEntry
 
	// Load config
	cfg, err := config.Load()
	if err != nil {
		log.Fatalf("Error loading config: %v", err)
	}
 
	ignorePatterns := cfg.IgnorePatterns
 
	err = filepath.WalkDir(srcDir, func(path string, d fs.DirEntry, walkErr error) error {
		if walkErr != nil {
			fmt.Printf("Error accessing path %s: %v\n", path, walkErr)
			return walkErr
		}
 
		if shouldSkip(path, ignorePatterns) {
			if d.IsDir() {
				return filepath.SkipDir
			}
			return nil
		}
 
		if d.IsDir() {
			return nil
		}
 
		ext := strings.ToLower(filepath.Ext(path))
 
		isMarkdown := ext == ".md" || ext == ".markdown"
		isAsset := isAssetFile(ext)
 
		if isMarkdown || isAsset {
			rel, _ := filepath.Rel(srcDir, path)
 
			entries = append(entries, FileEntry{
				Path:         path,
				RelativePath: rel,
				IsMarkdown:   isMarkdown,
				IsAsset:      isAsset,
			})
		}
 
		return nil
	})
 
	if err != nil {
		log.Fatalf("Error during directory traversal: %v", err)
	}
 
	return entries
}
 
func shouldSkip(path string, patterns []string) bool {
	lower := strings.ToLower(path)
 
	for _, p := range patterns {
		p = strings.ToLower(p)
 
		if strings.Contains(lower, p) {
			return true
		}
	}
 
	return false
}
 
func isAssetFile(ext string) bool {
	assetExt := map[string]bool{
		// document
		".pdf": true, ".csv": true,
 
		// audio
		".mp3": true, ".wav": true, ".ogg": true,
 
		// video
		".mp4": true, ".mov": true, ".webm": true,
 
		// image
		".png": true, ".jpg": true, ".jpeg": true, ".gif": true, ".svg": true, ".webp": true,
	}
 
	return assetExt[ext]
}

parameter filepath.WalkDir :

  • path string - path lengkap ke file/dir saat ini.
  • d fs.DirEntry - info dasar tentang entry (apakah file atau direktori, nama, dsb) tanpa melakukan os.Stat penuh (lebih efisien).
  • walkErr error - error yang mungkin muncul saat mencoba membaca entry; jika non-nil harus ditangani.

Package io

source:: https://pkg.go.dev/io

reference:: https://www.youtube.com/watch?v=dqvvN0WXU_M

  • IO atau singkatan dari Input Output, merupakan fitur di Golang yang digunakan sebagai standard untuk proses Input Output
  • Di Golang, semua mekanisme input output pasti mengikuti standard package io

Reader

  • Untuk membaca input, Golang menggunakan kontrak interface bernama Reader yang terdapat di package io
package main
 
import (
	"bufio"
	"fmt"
	"io"
	"strings"
)
 
func main() {
	input := strings.NewReader("This is long string\nwith new line\n")
 
	reader := bufio.NewReader(input)
 
	for {
		line, _, error := reader.ReadLine()
		if error == io.EOF {
			break
		}
		fmt.Println(string(line))
	}	
}

Writer

  • Untuk menulis ke output, Golang menggunakan kontrak interface bernama Writer yang terdapat di package io
package main
 
import (
	"bufio"
	"os"
)
 
func main() {
	writer := bufio.NewWriter(os.Stdout)
	_, _ = writer.WriteString("Hello world\n")
	_, _ = writer.WriteString("Belajar Golang\n")
	writer.Flush()
}

Implementasi IO

  • Penggunaan dari IO sendiri di Golang terdapat dibanyak package, sebelumnya contohnya kita menggunakan CSV Reader dan CSV Writer
  • Karena Package IO sebenarnya hanya kontrak untuk IO, untuk implementasinya kita harus lakukan sendiri
  • Tapi untungnya, Golang juga menyediakan package untuk mengimplementasikan IO secara mudah, yaitu menggunakan package bufio

Function Copy

package main
 
import (
	"fmt"
	"io"
	"os"
)
 
func main() {
	newPath := "folder/file.txt"
	copiedPath := "folder/copy.txt"
	fmt.Println("Copy file", copyFile(newPath, copiedPath))
 
}
 
func copyFile(srcPath, destPath string) error {
	src, err := os.Open(srcPath)
	if err != nil {
		return err
	}
 
	defer src.Close()
 
	dest, err := os.Create(destPath)
	if err != nil {
		return err
	}
	defer dest.Close()
 
	// dest dan src bukan string melainkan interface
	// destination dulu baru source, JANGAN KEBALIK
	_, err = io.Copy(dest, src)
 
	if err != nil {
		return err
	}
 
	return dest.Sync()
}
  • dest.Sync() Ini memastikan data benar-benar flush ke storage (berguna saat menulis file penting).

Copy

Argument jangan sampai kebalik, destination dulu baru source

Package bufio

source:: https://pkg.go.dev/bufio

  • Package bufio atau singkatan dari buffered io
  • Package ini digunakan untuk membuat data IO seperti Reader dan Writer

File Manipulation

File Management

  • Saat kita membuat atau membaca file menggunakan Package os, struct File merupakan implementasi dari io.Reader dan io.Writer
  • Oleh karena itu, kita bisa melakukan baca dan tulis terhadap File tersebut menggunakan Package io / bufio

Open File

  • Untuk membuat / membaca File, kita bisa menggunakan os.OpenFile(name, flag, permission)
  • name berisikan nama file, bisa absolute atau relative / local
  • flag merupakan penanda file, apakah untuk membaca, menulis, dan lain-lain
  • permission, merupakan permission yang diperlukan ketika membuat file, bisa kita simulasikan disini : https://chmod-calculator.com/
package main
 
import (
	"bufio"
	"fmt"
	"io"
	"os"
)
 
func createNewFile(name string, message string) error {
	file, err := os.OpenFile(name, os.O_CREATE|os.O_WRONLY, 0666)
	if err != nil {
		return err
	}
 
	defer file.Close()
	file.WriteString(message)
	return nil
 
}
 
func readFile(name string) (string, error) {
	file, err := os.OpenFile(name, os.O_RDONLY, 0666)
	if err != nil {
		return "", err
	}
 
	defer file.Close()
 
	reader := bufio.NewReader(file)
	var message string
	for {
		line, _, err := reader.ReadLine()
		if err == io.EOF {
			break
		} else {
			message += string(line) + "\n"
		}
	}
	return message, nil
}
 
func addToFile(name string, message string) error {
	file, err := os.OpenFile(name, os.O_RDWR|os.O_APPEND, 0666)
	if err != nil {
		return err
	}
 
	defer file.Close()
	file.WriteString(message)
	return nil
 
}
 
func main() {
	createNewFile("sample.log", "This is sample text")
	result, _ := readFile("sample.log")
	addToFile("sample.log", "\ntambah line baru")
	fmt.Printf(result)
}

Package Lainnya