Style Guide ini ada sebagai pedoman dalam ngoding Go berdasarkan aspek best practice, memory safety dan performance.
Kita bisa menggunakan underscore untuk mempermudah membaca number
Bad | Good |
---|---|
number := 10000000 |
better := 10_000_000 |
Deklarasi mutex tidak perlu menggunakan pointer karena dia zero value, pointer hanya akan meningkatkan kompleksitas.
Bad | Good |
---|---|
mu := new(sync.Mutex)
mu.Lock() |
var mu sync.Mutex
mu.Lock() |
Tidak diperbolehkan mengembed mutex di struct karena Lock dan Unlock belong to mutex dan bukan struct nya.
Bad | Good |
---|---|
type SMap struct {
sync.Mutex
data map[string]string
}
func NewSMap() *SMap {
return &SMap{
data: make(map[string]string),
}
}
func (m *SMap) Get(k string) string {
m.Lock()
defer m.Unlock()
return m.data[k]
} |
type SMap struct {
mu sync.Mutex
data map[string]string
}
func NewSMap() *SMap {
return &SMap{
data: make(map[string]string),
}
}
func (m *SMap) Get(k string) string {
m.mu.Lock()
defer m.mu.Unlock()
return m.data[k]
} |
Ketika kita pass slice & map ke function, sebenarnya dia pass by reference. Sehingga jika ada update value di dalam function, variable awal juga akan berubah
Bad | Good |
---|---|
func (d *Driver) SetTrips(trips []Trip) {
d.trips = trips
}
trips := ...
d1.SetTrips(trips)
// Did you mean to modify d1.trips?
trips[0] = ... |
func (d *Driver) SetTrips(trips []Trip) {
d.trips = make([]Trip, len(trips))
copy(d.trips, trips)
}
trips := ...
d1.SetTrips(trips)
// We can now modify trips[0] without affecting d1.trips.
trips[0] = ... |
Begitu pula data yang diambil dari slice dia juga pass by reference
Bad | Good |
---|---|
type Stats struct {
mu sync.Mutex
counters map[string]int
}
// Snapshot returns the current stats.
func (s *Stats) Snapshot() map[string]int {
s.mu.Lock()
defer s.mu.Unlock()
return s.counters
}
// snapshot is no longer protected by the mutex, so any
// access to the snapshot is subject to data races.
snapshot := stats.Snapshot() |
type Stats struct {
mu sync.Mutex
counters map[string]int
}
func (s *Stats) Snapshot() map[string]int {
s.mu.Lock()
defer s.mu.Unlock()
result := make(map[string]int, len(s.counters))
for k, v := range s.counters {
result[k] = v
}
return result
}
// Snapshot is now a copy.
snapshot := stats.Snapshot() |
Dalam 1 folder kita bisa memiliki nama package yang berbeda misal user
untuk base user dan user_test
untuk file unit
test user. Hal ini berfungsi agar unexported function tidak muncul.