Go语言中接口的类型判断和转换

摘要

Go语言中的接口和Java中的接口在定义方面区别不是特别大,当然也有区别,比如Go接口中不能有数据字段,可以嵌套接口;但是却在实现是大有不同,Java中一种类型(类)要实现某个接口则需要通过implements关键指名实现的接口名称,而Go中任何类型的方法集中只要拥有与接口对应的全部方法,就表明它 "实现" 了该接口,不用在该类型上显式添加接⼝声明。

接口定义

type Ier interface {
    hello() string
}

type Nuller interface {
	
}

上面定义了两个接口,接口Ier声明了一个方法,接口Nuller没有声明方法,通常没有声明方法的接口称为空接口或者标记接口,这就意味着任何类型都实现了空接口,作用和Java中的Object相似。

实现接口

type Chinese struct {
}

func (this *Chinese) hello() string {
	return "你好"
}

type Japanese struct {
}

func (this *Japanese) hello() string {
	return "こんにちは"
}

type English struct {
}

func (this *English) hello() string {
	return "Hello"
}

func (this *English) f1(){

}

func (this *English) f2(){

    
}

上面定义了三种类型,分别都定义和Ier接口方法签名相同的方法,因此这种类型都实现了Ier接口,同时也都实现了Nuller接口

定义函数

func greeting(ier Ier) {
	fmt.Println(ier.hello())
}

在定义函数的时候参数类型为接口类型,运行时将根据传递给函数的目标对象来运行对应实现的方法。

  • 如果目标对象的类型结构体中方法的recevier(接收者)是指针类型,则greeting函数传入的是一个指针对象。如果传入值对象将运行时错误,如下所示:
func (this *Chinese) hello() string {
	return "你好"
}

//直接传入值对象
greeting(Chinese{})

//输出
.\appath.go:54: cannot use Chinese literal (type Chinese) as type Ier in argument to greeting:
	Chinese does not implement Ier (hello method has pointer receiver)

  • 如果目标对象的类型结构体中方法的recevier(接受者)是值类型,则greeting函数传入的参数可以是值对象,也可以是指针对象。
func (this Chinese) hello() string {
	return "你好"
}

  • 产生上诉问题的原因是:每中类型都有与之关联的方法集参考:Go学习笔记第四版5.3方法集

    • 类型 T 的方法集包含全部receiver T的方法
    • 类型 *T 的方法集包含全部receiver T + *T的方法
    • 类型S包含匿名字段T, 则S的方法集包含T的方法
    • 类型S包含匿名字段*T, 则S的方法集包含T + *T的方法
    • 不管嵌入T*T, 则*S的方法集总是包含T + *T的方法

测试

  • 代码示例
	chinese := &Chinese{}
	japanese := &Japanese{}
	english := &English{}

	var iers = [...]Ier{
		chinese, japanese, english,
	}

	//不同语言的问候
	for _, ier := range iers {
		greeting(ier)
	}
	    

  • 输出结果
你好
こんにちは
Hello

类型判断

  • 代码示例
//类型判断
	fmt.Println("类型判断")
	var typeassert = func(ier interface{}) {
		if v, ok := ier.(Chinese); ok {
			fmt.Printf("%T is Chinese Type \n", v)
		}
		if v, ok := ier.(*Chinese); ok {
			fmt.Printf("%T is Pointer to Chinese Type \n", v)
		}
		if v, ok := ier.(Japanese); ok {
			fmt.Printf("%T is Japanese Type \n", v)
		}

		if v, ok := ier.(*Japanese); ok {
			fmt.Printf("%T is Pointer to Japanese Type \n", v)
		}

		if v, ok := ier.(English); ok {
			fmt.Printf("%T is  English Type \n", v)
		}
		if v, ok := ier.(*English); ok {
			fmt.Printf("%T is Pointer to English Type \n", v)
		}
	}
	ier = new(English)
	typeassert(ier)
	ier = Chinese{}
	typeassert(ier)
  • 输出结果
类型判断
*main.English is Pointer to English Type 
main.Chinese is Chinese Type 

类型转换

  • 代码示例
var ier interface{}

//	类型转换
fmt.Println("类型转换")
var typeswitch = func(ier interface{}) {
        switch t := ier.(type) {
	case Chinese:
		fmt.Printf("Chinese Type %T\n", t)
	case *Chinese:
		fmt.Printf("Pointer to Chinese Type %T\n", t)
	case Japanese:
		fmt.Printf("Japanese Type %T\n", t)
	case *Japanese:
        	fmt.Printf("Pointer to Japanese Type %T\n", t)
	case English:
		fmt.Printf("English Type %T\n", t)
	case *English:
		fmt.Printf("Pointer to English Type %T\n", t)
	default:
		fmt.Printf("unexpected type %T\n", t)
	}
}
ier = Chinese{}
typeswitch(ier)
ier = &English{}
typeswitch(ier)
  • 输出结果
类型转换
Chinese Type main.Chinese
Pointer to English Type *main.English

转载于:https://my.oschina.net/aiilive/blog/510303

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值