美文网首页golang_rookie我的专题
Go语言学习笔记 - 接口

Go语言学习笔记 - 接口

作者: 技术学习 | 来源:发表于2016-08-24 14:25 被阅读138次

接口定义

接口是一个或多个方法签名集合,任何类型的方法集中只要拥有与之对应的全部方法,就表示它“实现”了该接口,无须在该类型上显示添加接口声明。
  所谓对应方法,是指有相同名称、参数列表(不包含参数名)以及返回值。发然,该类型还可以有其他方法。

  • 接口命名习惯以er结尾,结构体。
  • 接口只有方法签名,没有实现。
  • 接口没有数据字段。
  • 可在接口中嵌入其他接口。
  • 类型可以实现多个接口。
      空接口interface{}没有任何方法签名,也就意味着任何类型都实现了空接口。其作用类似面向对象语言中的根对象object。
func Print(v interface{}) {
  fmt.Printf("%T: %v\n", v, v)
}
func main() {
  Print(1)
  Print("Hello, World!")
}
//输出:
int: 1
string: Hello, World!

匿名接口可用用作变量类型,或结构成员。

type Tester struct {
  s interface {
    String() string
  }
}
type User struct {
  id  int
  name string
}
func (self *User) String() string {
  return fmt.Sprintf("user %d, %s", self.id, self.name)
}
func main() {
  t := Tester{&User{1, "Tom"}}
  fmt.Println(t.s.String())
}
//输出:
user 1, Tom

执行机制

接口对象由接口表 (interface table) 指针和数据指针组成。
runtime.h

struct Iface
{
  Itab* tab;
  void* data;
};
struct Itab
{
  InterfaceType* inter;
  Type* type;
  void (*fun[])(void);
};

接口表存储元数据信息,包括接口类型、动态类型,以及实现接口的方法指针。无论是反射还是通过接口调用用方法,都会用到这些信息。
  数据指针持有的是目标对象的只读复制品,复制完整对象或指针。

type User struct {
  id int
  name string
}
func main() {
  u := User{1, "Tom"}
  var i interface{} = u
  u.id = 2
  u.name = "Jack"
  fmt.Printf("%v\n", u)
  fmt.Printf("%v\n", i.(User))
}
//输出:
{2 Jack}
{1 Tom}

接口转型返回临时对象,只有使用指针才能修改其状态。

type User struct {
  id int
  name string
}
func main() {
  u := User{1, "Tom"}
  var vi, pi interface{} = u, &u
  // vi.(User).name = "Jack" // Error: cannot assign to vi.(User).name
  pi.(*User).name = "Jack"
  fmt.Printf("%v\n", vi.(User))
  fmt.Printf("%v\n", pi.(*User))
}
//输出:
{1 Tom}
&{1 Jack}

接口转换

利用类型推断,可判断接口对象是否是某个具体的接口或类型。还可用用 switch 做批量类型判断,不支持 fallthrough。

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("unknown")
  }
}

超集接口对象可转换为子集接口,反之出错。

接口技巧

让编译器检查,以确保某个类型实现接口。

var _ fmt.Stringer = (*Data)(nil)

某些时候,让函数直接 "实现" 接口能省不少事。

type Tester interface {
  Do()
}
type FuncDo func()
func (self FuncDo) Do() { self() }
func main() {
  var t Tester = FuncDo(func() { println("Hello, World!") })
  t.Do()
}

相关文章

  • 笨办法学golang(三)

    这是Go语言学习笔记第三篇。 Go语言学习笔记参考书籍「Go语言圣经」以及Go官方标准库 Go语言基本类型主要有布...

  • 笨办法学golang(二)

    这是Go语言学习笔记的第二篇文章。 Go语言学习笔记参考书籍「Go语言编程」、Go官方标准库 前文提要 上篇文章中...

  • go语言基础

    go语言基础 go 语言接口

  • 笨办法学golang(四)

    这是Go语言学习笔记的第四篇 Go语言学习笔记参考书籍「Go语言圣经」以及Go官方标准库 数组 数组是指一系列同类...

  • Go语言学习笔记 - 接口

    接口定义 接口是一个或多个方法签名集合,任何类型的方法集中只要拥有与之对应的全部方法,就表示它“实现”了该接口,无...

  • Go 语言极速入门

    本系列文章主要是记录《Go 语言实战》和《Google 资深工程师深度讲解 Go 语言》的学习笔记。 Go 语言极...

  • Go语言学习笔记-interface接口✨

    接口是一个或多个方法签名的集合,任何类型的方法集中只要拥有与之对应的全部方法, 就表 它 "实现" 了该接 , 必...

  • Golang学习笔记---“泛型”的实现

    Golang学习笔记---“泛型”的实现 大家都知道,go语言中是没有泛型的,但是我们可以通过空接口的方式来实现泛...

  • Golang相关电子书

    Golang相关电子书,会不定期更新 Go语言程序设计 Go语言学习笔记.雨痕(详细书签) Go语言·云动力(云计...

  • Golang学习笔记---方法和接口方法的使用

    Golang学习笔记---方法和接口方法的使用 源码Github链接methodAndInterface.go

网友评论

    本文标题:Go语言学习笔记 - 接口

    本文链接:https://www.haomeiwen.com/subject/gtqosttx.html