---
# System prepended metadata

title: 'Day 23 : Golang Interface'
tags: [About Go]

---

# Day 23 : Golang Interface

## interface
先舉的生活的例子來看看什麼是介面。介面可以定義特定事務的所有行為，例如我們將「寵物」當作一個介面，裡面可能有「吃飯」、「睡覺」、「玩樂」(~~怎麼跟人類很像?~~)，那不管是「狗」、「貓」還是「鳥」，只要都為這些行為，就可以當做是「寵物」。因此不論是「狗」、「貓」還是「鳥」都可以被視為是「寵物」這個介面的實現。



接下來回到[A Tour of Go](https://go.dev/tour/methods/9)定義的interface如下
>*An **interface type** is defined as a set of method signatures.
A value of interface type can hold any value that implements those methods.*

在說明struct的時候，可以透過receiver function針對我們自己定義的結構體綁定method，一個interface其實就是定義該物件可以使用的全部方法(a set of method signatures)。而如果有個型別定義了完全相同的方法，就等於實現(implement)這個介面了。

## 定義與使用
但 *A value of interface type can hold any value that implements those methods* 這句話到底在說什麼，還是看不太懂，那就用寵物和行為的方式來試著瞭解看看吧。

首先定義一個Pet的interface，裡面有三個方法:Sleep()、Play()、Eat()。
接著定義一個Dog、Cat的結構體，與專屬這個型別的三個型為Sleep()、Play()、Eat()。
這時候由於Dog、Cat的三個行為讓Dog、Cat滿足Pet這個介面的規範，**Dog、Cat個型別都可以視為Pet型別**，此時在第45行將p定義是Pet介面型別，可以直接在p上使用Sleep()、Play()、Eat()方法。
最後如果不想養狗狗了(舉例而已，不要棄養)想要養貓，可以直接`p = Cat{"Orange"}`給新的值，不用透過`cat := Cat{"Orange"}`再宣告新的變數。


```go=
package main

import "fmt"

type Pet interface {
    Sleep() string
    Play() string
    Eat() string
}

type Dog struct {
    name string
}

func (d Dog) Sleep() string {
    return fmt.Sprintf("I am %s, I am sleeping", d.name)
}

func (d Dog) Play() string {
    return fmt.Sprintf("I am %s, I am having fun", d.name)
}

func (d Dog) Eat() string {
    return fmt.Sprintf("I am %s, I am eating", d.name)
}

type Cat struct {
    name string
}

func (c Cat) Sleep() string {
    return fmt.Sprintf("I am %s, I am sleeping", c.name)
}

func (c Cat) Play() string {
    return fmt.Sprintf("I am %s, I am having fun", c.name)
}

func (c Cat) Eat() string {
    return fmt.Sprintf("I am %s, I am eating", c.name)
}


func main() {
    var p Pet
    p = Dog{"White"}
    fmt.Println(p.Sleep()) // I am White, I am sleeping
    fmt.Println(p.Eat()) // I am White, I am eating
    
    // 棄狗養貓

    p = Cat{"Orange"}
    fmt.Println(p.Sleep()) // I am Orange, I am sleeping
    fmt.Println(p.Play()) // I am Orange, I am having fun
}
```

## 後記
interface真的博大精深，明天再繼續介紹空介面和type assertion吧


## References
1. [A Tour of Go - interface](https://go.dev/tour/methods/9)
2. [Effective Go - interface](https://go.dev/doc/effective_go#interfaces)
3. [Day12 Go神奇的介面與斷言(Interface, assertion)](https://hackmd.io/@goFamily/Sk2bkuvqw)


###### tags: `About Go`