Belajar Generic Types Di Golang
Halo semua ditulisan kali ini aku akan bahas tentang Generic Types di Go. Sebenarnya Generic types sendiri masih tergolong baru rilis di go yaitu pada versi go1.18. Diawal mungkin ada yang bingung kegunaannya generic types itu seperti apa di golang. Nah, pertanyaan yang sama pernah dilontarkan oleh teman kerja pada saat meeting diskusi teknis di kantor.
Contoh Fungsi Generic
Ada hal yang paling meresahkan saat aku coding dengan golang. Contohnya seperti ini: jadi ada beberapa library ataupun code di mini project saya yang tidak konsisten dalam penggunaan tipe data. Dan saya ingat betul itu library dibuat secepat mungkin karna kebutuhan yang mendesak. Sebagai contoh saya punya fungsi getUserByID dengan parameter id tipe datanya int.
func GetUserByID(id int) {
// get user query ..
}
lalu ada service / repo lain yang menggunakan library tersebut, tapi implementasinya beragam, karna id itu int, ada yang benar-benar passing int, ada juga yang dari int64 konversi dulu ke int. Nah dari contoh itu aku pikir sepertinya bisa dijadikan 1 types baru, aku kasih nama Number misalnya, dan number ini union(gabungan) dari int, int32, int64. Misalnya ada yang makain fungsi GetUserByID passingnya int64 ya tetap bisa tanpa mesti konversi lagi.
Jadi untuk membuat satu generic types baru hampir sama seperti membuat interface di go, contohnya seperti ini:
type Number interface {
int | int32 | int64
}
lalu fungsi GetUser, ya aku modif dikit jadi seperti ini:
func GetUserByID[number Number](a number) {
// get user query
}
// GetUserByID(1)
// GetUserByID(int32(1))
// GetUserByID(int64(1))
sampai disini kita sudah membuat tipe datanya makin generic, tidak tergantung pada satu tipe data.
Contoh Parsing JSON
Jadi ceritanya aku sering dapat response json seperti ini:
// json 1
{
"message": "Success",
"data": {
"id": 1
}
}
// json2
{
"message": "Success",
"data": [
{
"id": 1
}
]
}
bisa dilihat perbedaan dari bentuknya ialah isi dari datanya saja, dan hal yang sering aku lakukan adalah buat struct untuk setiap model response dan akhirnya structnya makin banyak, misalnya seperti ini:
type ResponseJSON1Data struct {
ID int64 `json:"id"`
}
type ResponseJSON1 struct {
Data ResponseJSON1Data `json:"data"`
}
type ResponseJSON2 struct {
Data ResponseJSON1Data `json:"data"`
}
dengan adanya generic type di go, kita bisa membuat ini sederhana. Karna kita sudah tau yang berubah-ubah itu cuman isi datanya saja, jadi kita perlu buat data itu menjadi generic. Caranya ialah pertama kita buat dulu struct untuk responsenya,
type (
Response struct[T ResponseData]{
Message string `json:"message"`
Data T `json:"data"
}
)
setelah itu baru kita buat struct datanya contohnya saya gunakan GetUser dan GetUsers, dan jangan lupa buat generic types dengan nama ResponseData dan isinya adalah union dari struct yang dibutuhkan,
type (
// GetUser is struct for user
GetUser struct {
ID int64 `json:"id"`
}
// GetUsers slice of Get User
GetUsers []GetUser
// ResponseData ...
ResponseData interface {
GetUser | GetUsers
}
)
dan saatnya kita testing, jadi saya buat json string simple dan saya unmarshal ke structnya,
func main() {
var user Response[GetUser]
var users Response[GetUsers]
testJSONString := `{"data": {"id":1}}`
err := json.Unmarshal([]byte(testJSONString), &user)
if err != nil {
log.Fatal(err)
}
testGetUsersJSONStr := `{"data": [{"id":1}]}`
err = json.Unmarshal([]byte(testGetUsersJSONStr), &users)
if err != nil {
log.Fatal(err)
}
fmt.Println(user.Data)
fmt.Println(users.Data)
}
// outputnya:
// {1} -> GetUser
// [{1}] -> GetUsers
dengan bantuan Generic Types golang kita bisa focus ke datanya saja, jadi tidak perlu buat struct yang banyak lagi. Berikut saya
Referensi: