# Interface

Interface adalah adalah kumpulan definisi method yang tidak memiliki isi (hanya definisi saja) yang dibungkus dengan nama tertentu.

Interface merupakan tipe data. Nilai objek bertipe interface zero value-nya adalah `nil`. Interface mulai bisa digunakan jika sudah ada isinya, yaitu objek konkret yang memiliki definisi method yang sama dengan yang ada di interface.

```go
type BangunDatar interface {
    luas() int
    keliling() int
}
```

#### Lalu yang menjadi pertanyaan, kenapa dan kapan menggunakan Interface?

Menulis kode yang fleksibel, dapat digunakan kembali, dan modular sangat penting dalam mengembangkan program. Ini juga adalah kenapa Go dibuat. Go sangat mendukung penulisan code yang clean, simple, reliable, dan efficient.&#x20;

Jadi Interface sebenarnya adalah tools yang bisa kita pakai atau tidak. Tetapi Interface dapat membuat kode menjadi clean, shorter, dan more readable.

### Mendefenisikan Behaviour

Sebelum masuk ke contoh Interface lebih detail, mari kita lihat studi kasus berikut:

```go
package main

import "fmt"

type Persegi struct {
	sisi float64
}

func (persegi Persegi) luas() float64 {
	return persegi.sisi * persegi.sisi
}

type PersegiPanjang struct {
	panjang float64
	lebar   float64
}

func (persegiPanjang PersegiPanjang) luas() float64 {
	return persegiPanjang.panjang * persegiPanjang.lebar
}

type Segitiga struct {
	alas   float64
	tinggi float64
}

func (segitiga Segitiga) luas() float64 {
	return 0.5 * (segitiga.alas * segitiga.tinggi)
}

func main() {
	p := Persegi{sisi: 5}
	luasPersegi := luasBangunDatar(p)
	fmt.Println(luasPersegi)

	pp := PersegiPanjang{panjang: 4, lebar: 6}
	luasPersegiPanjang := luasBangunDatar(pp)
	fmt.Println(luasPersegiPanjang)

	s := Segitiga{alas: 20, tinggi: 10}
	luasSegitiga := s.luas()
	fmt.Println(luasSegitiga)
}

```

Dari kode di atas tidak ada yang salah. Jika dijalankan hasilnya pun akan sesuai.

![Menampilkan masing-masing luas bangun datar](/files/-MScZ24S8co6kC1goWHc)

Kita bisa lihat ada behaviour yang mirip diantara masing-masing `struct` yaitu sama-sama memiliki method `luas` . Untuk itu kita akan membuat `interface` untuk menampung method tersebut.

### Mendefenisikan Interface

Untuk membuat tipe data Interface kita membutuhkan keyword `type` dan `interface` . Kita akan membuat `interface` bernama `BangunDatar` :

```go
type BangunDatar interface {
    luas() float64
}
```

Lalu kita akan membuat function yang memiliki parameter dengan tipe data `interface` .

```go
func luasBangunDatar(b BangunDatar) float64 {
	return b.luas()
}
```

Kita akan coba menggabungkan kedua kode di atas dengan kode sebelumnya:

```go
package main

import "fmt"

type BangunDatar interface {
	luas() float64
}

type Persegi struct {
	sisi float64
}

func (persegi Persegi) luas() float64 {
	return persegi.sisi * persegi.sisi
}

type PersegiPanjang struct {
	panjang float64
	lebar   float64
}

func (persegiPanjang PersegiPanjang) luas() float64 {
	return persegiPanjang.panjang * persegiPanjang.lebar
}

type Segitiga struct {
	alas   float64
	tinggi float64
}

func (segitiga Segitiga) luas() float64 {
	return 0.5 * (segitiga.alas * segitiga.tinggi)
}

func main() {
	p := Persegi{sisi: 5}
	luasPersegi := luasBangunDatar(p)
	fmt.Println(luasPersegi)

	pp := PersegiPanjang{panjang: 4, lebar: 6}
	luasPersegiPanjang := luasBangunDatar(pp)
	fmt.Println(luasPersegiPanjang)

	s := Segitiga{alas: 20, tinggi: 10}
	luasSegitiga := s.luas()
	fmt.Println(luasSegitiga)
}

func luasBangunDatar(b BangunDatar) float64 {
	return b.luas()
}
```

Jadi fungsi `luasBangunDatar` tidak memperdulikan parameter nilai dari masing-masing bangun datar. Kita dapat menambahkan sebanyak mungkin bangun datar yang kita ingin hitung luasnya denga catatan `struct` harus memiliki method yang terdaftar pada `interface` dan memiliki isi sesuai dengan konteksnya masing-masing.

### Studi kasus #2

Perhatikan kode di bawah ini:

```go
package main

import "fmt"

type Article struct {
    Title  string
    Author string
}

func (a Article) String() string {
    return fmt.Sprintf("The %q article was written by %s.", a.Title, a.Author)
}

type Book struct {
    Title  string
    Author string
    Pages  int
}

func (b Book) String() string {
    return fmt.Sprintf("The %q book was written by %s.", b.Title, b.Author)
}

type Stringer interface {
    String() string
}

func main() {
    a := Article{
        Title:  "Understanding Interfaces in Go",
        Author: "Sammy Shark",
    }
    Print(a)

    b := Book{
        Title:  "All About Go",
        Author: "Jenny Dolphin",
        Pages:  25,
    }
    Print(b)
}

func Print(s Stringer) {
    fmt.Println(s.String())
}
```

![](/files/-MScbOnXxvcpRq_7sVJo)

Pada studi kasus di atas ada kesamaan behaviour yaitu kedua `struct` sama-sama memiliki method `String` untuk menampilkan teks informasi Buku dan Artikel.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://davidwinalda94.gitbook.io/mastering-golang/interface.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
