go介面

JasBin2008發表於2020-10-26

介面實現原理和型別轉換

  • 接⼝命名習慣以 er 結尾,結構體。
  • 接⼝只有⽅法簽名,沒有實現。
  • 接⼝沒有資料欄位。
  • 可在接⼝中嵌⼊其他接⼝。
  • 型別可實現多個接⼝。

原理

接⼝物件由接⼝表 (interface table) 指標和資料指標組成

struct Iface
{
    Itab* tab;
    void* data;
};

示例:使用介面訪問物件

type User struct {
    id int
    name string
}

func main() {
    u := User{1, "Tom"}
    var i interface{} = u
    fmt.Printf("%v\n", i.(User))
}

介面轉換

示例一:判斷物件的具體介面或型別

type User struct {
	id int
	name string
}

func (self *User) String() string {
	return fmt.Sprintf("%d, %s", self.id, self.name)
}

func main() {
	var o interface{} = &User{1,"tom"}

	switch v := o.(type) {
	case nil: //o == nil
		fmt.Println(nil)
	case fmt.Stringer: //interface
		fmt.Println(v)
	case func() string: //func
		fmt.Println(v())
	case *User: //*struct
		fmt.Printf("%d, %s\n", v.id, v.name)
	default:
		fmt.Println("unkown")
	}
}

示例二:超級介面轉換為子集介面

type Stringer interface { //子集介面
	String() string
}

type Printer interface { //超集介面
	Stringer
	Print()
}

type User struct {
	id int
	name string
}

func (self *User) String() string {
	return fmt.Sprintf("%d, %s", self.id, self.name)
}

func (self *User) Print() {
	fmt.Println(self.String())
}

func main() {
	var o Printer = &User{1,"tom"}
	var s Stringer = o //超集介面轉子集介面
	fmt.Println(s.String())
}

相關文章