Struct Go
Struct dapat menyimpan sekumpulan data dengan tipe berbeda adalah tipe komposit. Go meninggalkan kelas dan inheritance sekaligus juga meninggalkan konstruktor sengaja melemahkan fungsi berorientasi objek Go bukan bahasa OOP tradisional tetapi Go tetap memiliki bayangan OOP melalui struct dan metode juga dapat mensimulasikan kelas. Berikut adalah contoh struct sederhana
type Programmer struct {
Name string
Age int
Job string
Language []string
}Deklarasi
Deklarasi struct sangat sederhana contohnya sebagai berikut
type Person struct {
name string
age int
}Struct itu sendiri dan field di dalamnya semuanya mematuhi cara penamaan huruf besar dan kecil untuk eksposur. Untuk beberapa field yang berdekatan dengan tipe yang sama tidak perlu mengulang deklarasi tipe sebagai berikut
type Rectangle struct {
height, width, area int
color string
}TIP
Saat mendeklarasikan field struct nama field tidak boleh duplikat dengan nama metode
Instansiasi
Go tidak ada konstruktor sebagian besar situasi menggunakan cara di bawah ini untuk menginstansiasi struct saat inisialisasi seperti map menentukan nama field lalu menginisialisasi nilai field
programmer := Programmer{
Name: "jack",
Age: 19,
Job: "coder",
Language: []string{"Go", "C++"},
}Tetapi juga dapat menghilangkan nama field saat menghilangkan nama field harus menginisialisasi semua field biasanya tidak direkomendasikan menggunakan cara ini karena keterbacaannya sangat buruk.
programmer := Programmer{
"jack",
19,
"coder",
[]string{"Go", "C++"}}Jika proses instansiasi kompleks Anda juga dapat menulis fungsi untuk menginstansiasi struct seperti di bawah ini Anda juga dapat memahaminya sebagai konstruktor
type Person struct {
Name string
Age int
Address string
Salary float64
}
func NewPerson(name string, age int, address string, salary float64) *Person {
return &Person{Name: name, Age: age, Address: address, Salary: salary}
}Tetapi Go tidak mendukung overload fungsi dan metode jadi Anda tidak dapat mendefinisikan parameter berbeda untuk fungsi atau metode yang sama. Jika ingin menginstansiasi struct dengan berbagai cara baik membuat beberapa konstruktor atau disarankan menggunakan pola options.
Pola Options
Pola options adalah pola desain yang sangat umum dalam bahasa Go dapat lebih fleksibel menginstansiasi struct kemampuan ekspansi kuat dan tidak perlu mengubah tanda tangan fungsi konstruktor. Misalkan ada struct seperti di bawah ini
type Person struct {
Name string
Age int
Address string
Salary float64
Birthday string
}Deklarasikan tipe PersonOptions menerima parameter tipe *Person harus berupa pointer karena kita akan memberikan nilai pada Person dalam closure.
type PersonOptions func(p *Person)Selanjutnya membuat fungsi options umumnya dimulai dengan With nilai pengembaliannya adalah fungsi closure.
func WithName(name string) PersonOptions {
return func(p *Person) {
p.Name = name
}
}
func WithAge(age int) PersonOptions {
return func(p *Person) {
p.Age = age
}
}
func WithAddress(address string) PersonOptions {
return func(p *Person) {
p.Address = address
}
}
func WithSalary(salary float64) PersonOptions {
return func(p *Person) {
p.Salary = salary
}
}Tanda tangan fungsi konstruktor yang sebenarnya dideklarasikan adalah sebagai berikut menerima parameter tipe PersonOptions variadic.
func NewPerson(options ...PersonOptions) *Person {
// Prioritas menerapkan options
p := &Person{}
for _, option := range options {
option(p)
}
// Penanganan nilai default
if p.Age < 0 {
p.Age = 0
}
......
return p
}Dengan begini untuk kebutuhan instansiasi yang berbeda hanya perlu satu konstruktor即可 menyelesaikan hanya perlu meneruskan fungsi Options yang berbeda
func main() {
pl := NewPerson(
WithName("John Doe"),
WithAge(25),
WithAddress("123 Main St"),
WithSalary(10000.00),
)
p2 := NewPerson(
WithName("Mike jane"),
WithAge(30),
)
}Pola functional options dapat dilihat di banyak proyek open source cara instansiasi gRPC Server juga menggunakan pola desain ini. Pola functional options hanya cocok untuk instansiasi kompleks jika parameter hanya beberapa sederhana disarankan tetap menggunakan konstruktor biasa untuk menyelesaikannya.
Komposisi
Di Go hubungan antar struct dinyatakan melalui komposisi dapat komposisi eksplisit juga dapat komposisi anonim yang terakhir penggunaannya lebih mirip inheritance tetapi pada dasarnya tidak ada perubahan. Misalnya
Cara komposisi eksplisit
type Person struct {
name string
age int
}
type Student struct {
p Person
school string
}
type Employee struct {
p Person
job string
}Saat menggunakan perlu secara eksplisit menentukan field p
student := Student{
p: Person{name: "jack", age: 18},
school: "lili school",
}
fmt.Println(student.p.name)Sedangkan komposisi anonim tidak perlu secara eksplisit menentukan field
type Person struct {
name string
age int
}
type Student struct {
Person
school string
}
type Employee struct {
Person
job string
}Nama field anonim secara default adalah nama tipe pemanggil dapat langsung mengakses field dan metode tipe tersebut tetapi selain lebih nyaman tidak ada perbedaan dengan cara pertama.
student := Student{
Person: Person{name: "jack",age: 18},
school: "lili school",
}
fmt.Println(student.name)Pointer
Untuk pointer struct tidak perlu dereferensi dapat langsung mengakses konten struct contohnya sebagai berikut
p := &Person{
name: "jack",
age: 18,
}
fmt.Println(p.age,p.name)Saat dikompilasi akan dikonversi menjadi (*p).name (*p).age sebenarnya tetap perlu dereferensi tetapi saat pengkodean dapat dihilangkan dianggap sebagai sugar sintaks.
Tag
Tag struct adalah bentuk meta programming dikombinasikan dengan refleksi dapat membuat banyak fungsi ajaib formatnya adalah sebagai berikut
`key1:"val1" key2:"val2"`Tag adalah bentuk key-value dipisahkan dengan spasi. Toleransi kesalahan tag struct sangat rendah jika tidak menulis tag struct sesuai dengan format yang benar maka akan menyebabkan tidak dapat dibaca secara normal tetapi saat dikompilasi tidak akan ada error apa pun di bawah ini adalah contoh penggunaan.
type Programmer struct {
Name string `json:"name"`
Age int `yaml:"age"`
Job string `toml:"job"`
Language []string `properties:"language"`
}Penggunaan tag struct paling luas adalah definisi alias dalam berbagai format serialisasi penggunaan tag perlu dikombinasikan dengan refleksi untuk sepenuhnya mengeluarkan fungsinya.
Penyelarasan Memori
Distribusi memori field struct Go mengikuti aturan penyelarasan memori ini dilakukan untuk mengurangi jumlah akses CPU ke memori相应nya memori yang ditempati lebih banyak adalah jenis pertukaran ruang untuk waktu. Misalkan ada struct seperti berikut
type Num struct {
A int64
B int32
C int16
D int8
E int32
}Diketahui byte yang ditempati oleh tipe-tipe ini
int64menempati 8 byteint32menempati 4 byteint16menempati 2 byteint8menempati satu byte
Apakah penggunaan memori seluruh struct sepertinya 8+4+2+1+4=19 byte tentu saja tidak demikian menurut aturan penyelarasan memori而言 panjang penggunaan memori struct setidaknya adalah kelipatan integer dari field terbesar yang kurang maka dilengkapi. Yang terbesar dalam struct ini adalah int64 menempati 8 byte maka distribusi memori seperti yang ditunjukkan pada gambar di bawah ini

Jadi sebenarnya menempati 24 byte di antaranya 5 byte tidak berguna.
Mari lihat struct di bawah ini
type Num struct {
A int8
B int64
C int8
}Setelah memahami aturan di atas dapat dengan cepat memahami penggunaan memorinya juga 24 byte meskipun hanya memiliki tiga field membuang 14 byte.

Tetapi kita dapat menyesuaikan field mengubah menjadi urutan seperti berikut
type Num struct {
A int8
C int8
B int64
}Dengan begini memori yang ditempati menjadi 16 byte membuang 6 byte mengurangi pemborosan memori 8 byte.

Secara teoritis membuat field dalam struct didistribusikan sesuai dengan urutan yang wajar dapat mengurangi penggunaan memorinya. Tetapi dalam proses pengkodean aktual tidak ada alasan yang diperlukan untuk melakukan hal ini belum tentu dapat membawa peningkatan substansial dalam mengurangi penggunaan memori tetapi pasti akan meningkatkan tekanan darah dan beban mental pengembang terutama dalam bisnis beberapa field struct mungkin多达 puluhan atau ratusan jadi hanya做 pemahaman即可.
TIP
Jika Anda benar-benar ingin menghemat memori melalui metode ini dapat melihat dua pustaka ini
Mereka akan memeriksa struct dalam kode sumber Anda menghitung dan menata ulang field struct untuk meminimalkan memori yang ditempati struct.
Struct Kosong
Struct kosong tidak memiliki field tidak menempati ruang memori kita dapat melalui fungsi unsafe.SizeOf untuk menghitung ukuran byte yang ditempati
func main() {
type Empty struct {}
fmt.Println(unsafe.Sizeof(Empty{}))
}Output
0Ada banyak skenario penggunaan struct kosong misalnya yang disebutkan sebelumnya sebagai tipe nilai map dapat menggunakan map sebagai set untuk digunakan atau sebagai tipe channel hanya表示 channel tipe notifikasi.
