Go语言接口详解、类型断言

Go语言的接口隐式实现,即:
对于一个具体的类型,无需声明它实现了哪些接口,只要提供接口所必须的方法即可。
示例:

package main

import (
	"reflect"
)

// Mover 接口定义
type Mover interface {
	Move()
}

// Stopper 接口定义
type Stopper interface {
	Stop()
}

// 交通工具 接口定义
type Vehicle interface {
	// 组合了 Mover 和 Stopper 接口(称作嵌入式接口)
	Mover
	Stopper
}

// Car 类型定义
type Car struct {
	Speed int
}

// Car 实现了 Vehicle 接口的全部方法,即为实现了 Vehicle 接口
func (c *Car) Move() {
	println("Car move, speed =", c.Speed)
}

func (c *Car) Stop() {
	println("Car stop")
}

// moveTo 方法定义, 参数为 Vehicle 接口类型
func moveTo(vehicle Vehicle) {
	println("moveTo by ", reflect.TypeOf(vehicle).String())
	vehicle.Move()
	vehicle.Stop()
}

func main() {
	car := new(Car)
	car.Speed = 5

	// car 实现了 Vehicle 接口,可赋值给 Vehicle
	// 若 car 只实现了 Move 方法,这里会编译失败, 报错为:
	// *Car does not implement Vehicle (missing Stop method)
	moveTo(car)
}

程序输出:
moveTo by *main.Car
Car move, speed = 5
Car stop

接口判空

	var vehicle Vehicle  // vehicle 初始化为 nil
	var car *Car  // car 初始化为 nil
	vehicle = car  // 此时 vehicle != nil
	vehicle = (*Car)(nil)  // 此时 vehicle != nil
	vehicle = nil  // 此时 vehicle == nil

接口的值包括类型和该类型的值两个部分,称为接口的动态类型和动态值,接口是否为nil取决于动态类型,执行上述 vehicle = (*Car)(nil) 后,vehicle的动态类型为Car类型,所以 vehicle != nil

空接口类型 interface{}
任何值都可以赋给空接口类型 (类似 Java 的 Object 类型)

	var any interface{}
	any = 3.14
	any = "hello"
	any = new(Car)

类型断言

x.(T)

x 是接口类型表达式,T 可以是具体类型或接口类型(称为断言类型)
若x是T类型,将x转换为T类型并返回,否则操作崩溃

func main() {
	var car = new(Car)
	check(car)
}

func check(x interface{}) {
	var _ Vehicle = x.(Vehicle) // success
	var _ Mover = x.(Mover)     // success
	var _ *Car = x.(*Car)       // success
	var _ string = x.(string)   // panic: interface conversion: interface {} is *main.Car, not string
	x = nil
	var _ Vehicle = x.(Vehicle) // panic: interface conversion: interface is nil, not main.Vehicle
}

可识别联合
接口接受各种具体类型,运行时区分这些类型并分别处理,这种接口使用方式称作可识别联合。
是一种特设多态(比如函数重载,C++的模板特化)。

func main() {
	info(nil)
	info(3)
	info("hello")
	info(new(Car))
}

func info(x interface{}) {
	// 新的 x 只作用于 switch 代码块内,和外部的 x 不冲突
	// 这里直接使用 type 关键字
	switch x := x.(type) { 
	case nil:
		println("x is nil")
	case int, uint:  // case 两种类型,所以返回 interface{},包括类型和值
		println("x is int or unit, type =", reflect.TypeOf(x).String())
	case string:
		println("x is string, value =", x)
	default:
		println("x is invalid type:", reflect.TypeOf(x).String())
	}
}

输出为:
x is nil
x is int or unit, type = int
x is string, value = hello
x is invalid type: *main.Car

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值