Dasar-Dasar Reflection
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan GO di Coddy. Pelajaran 83 dari 107.
Refleksi memungkinkan program memeriksa dan memanipulasi strukturnya sendiri saat runtime. Package reflect Go menyediakan kemampuan ini, sehingga kamu dapat memeriksa tipe, membaca field struct, dan memanggil method secara dinamis.
Dua tipe inti dalam refleksi adalah reflect.Type dan reflect.Value. Kamu mendapatkannya menggunakan reflect.TypeOf() dan reflect.ValueOf():
import "reflect"
type Person struct {
Name string
Age int
}
p := Person{Name: "Alice", Age: 30}
t := reflect.TypeOf(p)
v := reflect.ValueOf(p)
fmt.Println(t.Name()) // Person
fmt.Println(t.Kind()) // struct
fmt.Println(v.NumField()) // 2Kamu bisa melakukan iterasi pada field struct untuk memeriksa nama, tipe, dan nilainya:
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
value := v.Field(i)
fmt.Printf("%s: %v\n", field.Name, value)
}
// Output:
// Name: Alice
// Age: 30Reflection sangat kuat, tetapi memiliki konsekuensi: reflection melewati pemeriksaan tipe saat kompilasi, berjalan lebih lambat daripada akses langsung, dan membuat kode lebih sulit dipahami. Gunakan secukupnya untuk tugas seperti marshaling JSON, pemetaan ORM, atau membangun utilitas generik saat tipe tidak diketahui pada waktu kompilasi.
Tantangan
MudahMari buat inspector struct yang menggunakan reflection untuk memeriksa struct apa pun dan melaporkan strukturnya! Ini adalah contoh penggunaan reflection yang praktis: membuat utilitas yang bekerja dengan tipe yang tidak diketahui saat compile.
Kamu akan mengatur kodemu dalam dua file:
inspector.go: Buat utilitas pemeriksaan berbasis reflection.Buat fungsi
InspectStruct(v any) stringyang menggunakan packagereflectuntuk memeriksa struct apa pun yang diberikan kepadanya. Fungsi ini harus mengembalikan laporan berformat yang berisi:- Nama tipe struct
- Kind struct (seharusnya "struct")
- Jumlah field
- Untuk setiap field: nama field, tipenya, dan nilai saat ini
Format output-nya harus seperti berikut:
Type: [TypeName] Kind: struct Fields: [count] - [FieldName] ([FieldType]): [Value] - [FieldName] ([FieldType]): [Value] ...Gunakan
reflect.TypeOf()untuk mendapatkan informasi tipe danreflect.ValueOf()untuk mengakses nilai field. Lakukan perulangan pada field menggunakanNumField(),Field(i)pada tipe untuk mendapatkan metadata, danField(i)pada nilai untuk mendapatkan nilai sebenarnya.main.go: Definisikan struct contoh dan gunakan inspector-mu.Baca tipe struct (
productatauemployee) dan nilai field-nya, lalu buat struct yang sesuai dan periksa struct tersebut.Untuk
product: Buat structProductdengan fieldName(string),Price(float64), danInStock(bool). Baca nama, harga, dan status stok.Untuk
employee: Buat structEmployeedengan fieldID(int),Name(string), danDepartment(string). Baca ID, nama, dan departemen.Berikan struct yang dibuat ke
InspectStructdan cetak hasilnya.
Input berikut akan diberikan:
- Baris 1: Tipe struct (
productatauemployee) - Baris berikutnya: Nilai field untuk tipe struct tersebut
Contohnya, jika diberikan:
product
Laptop
999.99
trueOutput-mu seharusnya:
Type: Product
Kind: struct
Fields: 3
- Name (string): Laptop
- Price (float64): 999.99
- InStock (bool): trueDan jika diberikan:
employee
42
Alice Johnson
EngineeringOutput-mu seharusnya:
Type: Employee
Kind: struct
Fields: 3
- ID (int): 42
- Name (string): Alice Johnson
- Department (string): EngineeringDan jika diberikan:
product
Headphones
79.50
falseOutput-mu seharusnya:
Type: Product
Kind: struct
Fields: 3
- Name (string): Headphones
- Price (float64): 79.5
- InStock (bool): falsePerhatikan bagaimana inspectormu bekerja dengan berbagai tipe struct tanpa mengetahui strukturnya terlebih dahulu. Inilah kekuatan reflection! Fungsi InspectStruct yang sama menangani struct Product dan Employee secara dinamis.
Coba sendiri
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
// Struct Product dengan field Name, Price, dan InStock
type Product struct {
Name string
Price float64
InStock bool
}
// Struct Employee dengan field ID, Name, dan Department
type Employee struct {
ID int
Name string
Department string
}
func main() {
reader := bufio.NewReader(os.Stdin)
// Baca tipe struct
structType, _ := reader.ReadString('\n')
structType = strings.TrimSpace(structType)
if structType == "product" {
// Baca field produk
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
priceStr, _ := reader.ReadString('\n')
priceStr = strings.TrimSpace(priceStr)
price, _ := strconv.ParseFloat(priceStr, 64)
inStockStr, _ := reader.ReadString('\n')
inStockStr = strings.TrimSpace(inStockStr)
inStock, _ := strconv.ParseBool(inStockStr)
// TODO: Buat struct Product dengan nilai yang telah dibaca
// TODO: Panggil InspectStruct dengan produk tersebut dan cetak hasilnya
} else if structType == "employee" {
// Baca field karyawan
idStr, _ := reader.ReadString('\n')
idStr = strings.TrimSpace(idStr)
id, _ := strconv.Atoi(idStr)
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
department, _ := reader.ReadString('\n')
department = strings.TrimSpace(department)
// TODO: Buat struct Employee dengan nilai yang telah dibaca
// TODO: Panggil InspectStruct dengan karyawan tersebut dan cetak hasilnya
}
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Objek
1Dasar-Dasar OOP di Go
File EksternalWorkspace Go dan modulePaket dan ImporNama yang Diekspor dan Tidak DieksporPengantar OOP di Gostruct sebagai classMendefinisikan method pada structPointer receiver vs value receiverInisialisasi structFungsi KonstruktorUlasan: Kalkulator Sederhana4Interface
Pengenalan InterfaceImplementasi ImplisitInterface sebagai KontrakInterface Kosong (any)Type AssertionType SwitchKomposisi InterfaceInterface Stringer & ErrorUlasan: Kalkulator Bentuk7Enkapsulasi
Field yang Diekspor vs Tidak DieksporEnkapsulasi Tingkat PackageMethod Getter dan SetterPenyembunyian Informasi di GoRingkasan: Data Siswa10Generics (Go 1.18+)
Pengantar GenericsParameter TipeBatasan TipeStruct GenerikCara Alternatif untuk Method GenerikRingkasan Koleksi Generik2Mendalami Tipe dan Struct
Tipe Dasar dan KompositDefinisi Tipe KustomTag StructStruct AnonimStruct BersarangNilai Nol dan Nilai BawaanRangkuman: Buku Kontak5Komposisi daripada Pewarisan
Mengapa Go Tidak Memiliki PewarisanDasar Penyematan StructPromosi methodMenyematkan Beberapa StructPenyematan vs AgregasiMembayangi method yang DisematkanRangkuman: Hierarki Karyawan8Penanganan Error & OOP
Interface errorTipe Error KustomPembungkusan Error (fmt.Errorf)Error Sentinelerrors.Is() dan errors.As()Panic, Defer, dan RecoverRangkuman: Parser File3Pointer dan Memori
Dasar-Dasar Pointer di GoPointer ke StructPass by Value vs ReferenceFungsi new()Garbage Collection di GoRekap: Pembuat Linked List6Polimorfisme di Go
Polimorfisme melalui InterfaceDuck Typing di GoAturan Pemenuhan InterfaceKoleksi PolimorfikInjeksi DependensiRangkuman: Pemroses Pembayaran9Konkruensi & OOP
Dasar-dasar GoroutineChannel & KomunikasiChannel Ber-buffer vs Tanpa BufferPernyataan selectsync.Mutex & sync.RWMutexsync.WaitGroupDesain Struct yang Aman untuk ThreadRingkasan: Worker Pool12Konsep OOP Lanjutan
Pola Opsi FungsionalPola Builder di GoMethod ChainingAlias Tipe vs DefinisiDasar-Dasar ReflectionGambaran Umum Pembuatan KodeLatihan sendiri: Compiler Go online