Skip to content
On this page

接口

  • go的接口是一种抽象的自定义类型,没法直接实例化,它声明了一个或者多个方法的签名;
  • 如果一个struct实现了一个接口定义的所有方法,我们就说这个struct实现了这个接口。注意这里的实现隐式的,不用显示声明某个struct实现了哪个接口

定义接口

Go
type interface_name interface {
  method1()
  method2()
  ...
}

实现接口

Go
type Sleeper interface {
	sleep()
}
type Dog struct {
	name string
	age  int
}
func (d Dog) sleep() {
	fmt.Printf("%s在睡觉,它今年%d岁了\n", d.name, d.age)
}

type Cat struct {
	name string
	like string
}

func (c Cat) sleep() {
	fmt.Printf("%s 在睡觉,它喜欢%s\n", c.name, c.like)
}

func main() {
	dog_one := Dog {
		name: "小黄",
		age: 2,
	}
	// 小黄在睡觉,它今年2岁了
	dog_one.sleep()

	cat_one := Cat {
		name: "kitty",
		like: "",
	}
	// kitty 在睡觉,它喜欢爬
	cat_one.sleep()
}

接口的多态

  • 多态就是同一个接口,对于不同的实例执行不同的操作;

如上面创建接口的例子,Dog结构体和Cat结构体都实现了sleep方法,做了不同的事情,这就是多态

Go
func main() {
  ...
  dog_one.sleep()
  cat_ont.sleep()
}

接口内部表示

  • 可以把接口的内部看做(type, value);

  • type接口底层的具体类型(Concrete Type);

  • value具体类型的值

Go
type Sleeper interface {
	sleep()
}
type Dog struct {
	name string
	age  int
}
func (d Dog) sleep() {
	fmt.Printf("%s在睡觉,它今年%d岁了\n", d.name, d.age)
}
func showInterfaceType(s Sleeper) {
	fmt.Printf("接口s的类型为%T, 值为%v\n", s, s)
}

func main() {
	var dog_two Sleeper
	dog_two = Dog {
		name: "小灰",
		age: 6,
	}
	showInterfaceType(dog_two) // 接口s的类型为main.Dog, 值为{小灰 6}
	dog_two.sleep() // 小灰在睡觉,它今年6岁了
}

空接口

  • 空接口特殊形式的接口类型,没有定义任何方法的接口就称为空接口;

  • 所有类型都至少实现了空接口,空接口表示为interface{}

  • 当函数的参数类型为空接口时,函数可以接受任何类型的参数

Go
func emptyInterface(i interface{}) {
	fmt.Printf("i的类型: %T, i的值: %v\n", i, i)
}

func main() {
	name := "张环"
	emptyInterface(name) // i的类型: string, i的值: 张环
	age := 22
	emptyInterface(age) // i的类型: int, i的值: 22
	isBoss := true
	emptyInterface(isBoss) // i的类型: bool, i的值: true
}
  • 接口都有两个属性,一个是,而另一个是类型,对于空接口来说,这两个属性都为nil
Go

func main() {
	var empty_interface interface {}
	// empty_interface 类型为<nil>, 值为<nil>
	fmt.Printf("empty_interface 类型为%T, 值为%v\n", empty_interface, empty_interface)
}
  • 使用空接口interface{}作为类型声明一个实例,这个实例就能承载任何类型的值
Go
func main() {
	var str interface {}
	str = "张环"
	fmt.Println(str) // 张环
	str = 88
	fmt.Println(str) // 88
	str = true
	fmt.Println(str) // true
	str = []string{"张环", "李朗"}
	fmt.Println(str) // [张环 李朗]
	str = map[string]int{
		"name": 2,
		"age": 22,
	}
	fmt.Println(str) // map[age:22 name:2]
}
  • 也可以定义一个接收任何类型的arrayslicemapstrcut
Go
func main() {
	any_type_value := make([]interface{}, 5)
	any_type_value[0] = "张环"
	any_type_value[1] = 22
	any_type_value[2] = map[int]int{1: 10, 2: 20}
	any_type_value[3] = []int{2, 22, 222}
	for idx, value := range any_type_value {
		fmt.Printf("第%d个值为%v\n", idx, value)
	    // 第0个值为张环
	    // 第1个值为22
	    // 第2个值为map[1:10 2:20]
	    // 第3个值为[2 22 222]
	    // 第4个值为<nil>
	}
}

类型断言

  • 类型断言用于提取接口的底层值(Underlying Value);

  • 使用interface.(Type)可以获取接口的底层值,其中接口interface的具体类型是Type;

Go
func assertType(i interface{}) {
	switch i.(type) {
		case int:
		  // int类型
			fmt.Println("int类型")
		case string:
		  // string类型
			fmt.Println("string类型")
		case bool:
		   // 布尔(bool)类型
			fmt.Println("布尔(bool)类型")
		default:
			fmt.Println("未知类型unknown")
	}
}

func main() {
	assertType(1)
	assertType("张环")
	assertType(false)
}