Interface kosong atau empty interface yang dinotasikan dengan interface{}
merupakan tipe data yang sangat spesial. Variabel bertipe ini bisa menampung segala jenis data, bahkan array, pointer, apapun. Tipe data dengan konsep ini biasa disebut dengan dynamic typing.
interface{}
merupakan tipe data, sehingga cara penggunaannya sama seperti pada tipe data lainnya, hanya saja nilai yang diisikan bisa apa saja. Contoh:
package main
import "fmt"
func main() {
var secret interface{}
secret = "ethan hunt"
fmt.Println(secret)
secret = []string{"apple", "manggo", "banana"}
fmt.Println(secret)
secret = 12.4
fmt.Println(secret)
}
Keyword interface
seperti yang kita tau, digunakan untuk pembuatan interface. Tetapi ketika ditambahkan kurung kurawal ({}
) di belakang-nya (menjadi interface{}
), maka kegunaannya akan berubah, yaitu sebagai tipe data.
Agar tidak bingung, coba perhatikan kode berikut.
var data map[string]interface{}
data = map[string]interface{}{
"name": "ethan hunt",
"grade": 2,
"breakfast": []string{"apple", "manggo", "banana"},
}
Pada kode di atas, disiapkan variabel data
dengan tipe map[string]interface{}
, yaitu sebuah koleksi dengan key bertipe string
dan nilai bertipe interface kosong interface{}
.
Kemudian variabel tersebut di-inisialisasi, ditambahkan lagi kurung kurawal setelah keyword deklarasi untuk kebutuhan pengisian data, map[string]interface{}{ /* data */ }
.
Dari situ terlihat bahwa interface{}
bukanlah sebuah objek, melainkan tipe data.
Variabel bertipe interface{}
bisa ditampilkan ke layar sebagai string
dengan memanfaatkan fungsi print, seperti fmt.Println()
. Tapi perlu diketahui bahwa nilai yang dimunculkan tersebut bukanlah nilai asli, melainkan bentuk string dari nilai aslinya.
Hal ini penting diketahui, karena untuk melakukan operasi yang membutuhkan nilai asli pada variabel yang bertipe interface{}
, diperlukan casting ke tipe aslinya. Contoh seperti pada kode berikut.
package main
import "fmt"
import "strings"
func main() {
var secret interface{}
secret = 2
var number = secret.(int) * 10
fmt.Println(secret, "multiplied by 10 is :", number)
secret = []string{"apple", "manggo", "banana"}
var gruits = strings.Join(secret.([]string), ", ")
fmt.Println(gruits, "is my favorite fruits")
}
Pertama, variabel secret
menampung nilai bertipe numerik. Ada kebutuhan untuk mengalikan nilai yang ditampung variabel tersebut dengan angka 10
. Maka perlu dilakukan casting ke tipe aslinya, yaitu int
, setelahnya barulah nilai bisa dioperasikan, yaitu secret.(int) * 10
.
Pada contoh kedua, secret
berisikan array string. Kita memerlukan string tersebut untuk digabungkan dengan pemisah tanda koma. Maka perlu di-casting ke []string
terlebih dahulu sebelum bisa digunakan di strings.Join()
, contohnya pada strings.Join(secret.([]string), ", ")
.
Teknik casting pada interface disebut dengan type assertions.
Variabel interface{}
bisa menyimpan data apa saja, termasuk data objek, pointer, ataupun gabungan keduanya. Di bawah ini merupakan contoh penerapan interface untuk menampung data objek pointer.
type person struct {
name string
age int
}
var secret interface{} = &person{name: "wick", age: 27}
var name = secret.(*person).name
fmt.Println(name)
Variabel secret
dideklarasikan bertipe interface{}
menampung referensi objek cetakan struct person
. Cara casting dari interface{}
ke struct pointer adalah dengan menuliskan nama struct-nya dan ditambahkan tanda asterisk (*
) di awal, contohnya seperti secret.(*person)
. Setelah itu barulah nilai asli bisa diakses.
Tipe []map[string]interface{}
adalah salah satu tipe yang paling sering digunakan (menurut saya), karena tipe data tersebut bisa menjadi alternatif tipe slice struct.
Pada contoh berikut, variabel person
dideklarasikan berisi data slice map
berisikan 2 item dengan key adalah name
dan age
.
var person = []map[string]interface{}{
{"name": "Wick", "age": 23},
{"name": "Ethan", "age": 23},
{"name": "Bourne", "age": 22},
}
for _, each := range person {
fmt.Println(each["name"], "age is", each["age"])
}
Dengan memanfaatkan slice dan interface{}
, kita bisa membuat data array yang isinya adalah bisa apa saja. Silakan perhatikan contoh berikut.
var fruits = []interface{}{
map[string]interface{}{"name": "strawberry", "total": 10},
[]string{"manggo", "pineapple", "papaya"},
"orange",
}
for _, each := range fruits {
fmt.Println(each)
}