接口类型总是代表着某一种类型(即所有实现它的类型)的行为。
一个接口类型的声明通常会包含关键字type、类型名称、关键字interface以及由花括号包裹的若干方法声明。
type Animal interface {
Grow()
Move(string) string
}
接口类型中的方法声明是普通的方法声明的简化形式。
它们只包括方法名称、参数声明列表和结果声明列表。
其中的参数的名称和结果的名称都可以被省略。
不过,出于文档化的目的,建议写上它们。
因此,Move方法的声明至少应该是这样的:
Move(new string) (old string)
一个数据类型所拥有的方法集合中包含了某一个接口类型中的所有方法声明的实现,那么就可以说这个数据类型实现了那个接口类型。
不能在一个非接口类型的值上应用类型断言来判定它是否属于某一个接口类型的。
我们必须先把前者转换成空接口类型的值。
Go语言的类型转换规则定义了是否能够把一个类型的值转换另一个类型的值。
空接口类型即是不包含任何方法声明的接口类型,用interface{}表示,常简称为空接口。
正因为空接口的定义,Go语言中的包含预定义的任何数据类型都可以被看做是空接口的实现。
我们可以直接使用类型转换表达式把一个*Person类型转换成空接口类型的值.
p := Person{"Robert", "Male", , "Beijing"}
v := interface{}(&p)
然后就可以在v上应用类型断言了,即:
h, ok := v.(Animal)
类型断言表达式v.(Animal)的求值结果可以有两个。
第一个结果是被转换后的那个目标类型(这里是Animal)的值,
而第二个结果则是转换操作成功与否的标志。
显然,ok代表了一个bool类型的值。
它也是这里判定实现关系的重要依据。
package main

import (
"fmt"
) type humaner interface {
sayHello() //接口只有声明没有实现。
} type Studnt struct {
name string
age int
} func (tmp *Studnt) sayHello() {
fmt.Println("i am student")
} type Teacher struct {
name string
age int
} func (tmp *Teacher) sayHello() {
fmt.Println("i am Teacher")
} func whoSayHi(i humaner) {
i.sayHello()
} func main() {
//定义接口类型变量
var h humaner
//实现了此接口的方法类型,那么这个类型的变量就可以给i赋值。
s := &Studnt{"break", }
h = s
h.sayHello() t := &Teacher{"Tony", }
//通过接口调用实现多态
whoSayHi(s)
whoSayHi(t) //创建一个切片
x := make([]humaner, )
x[] = s
x[] = t
for _, hum := range x {
hum.sayHello()
}
}
package main

import (
"fmt"
) type humaner interface { //子集
sayHello() //接口只有声明没有实现。
} type persion interface { //超集
humaner //匿名字段继承sayHello
sing(lrc string)
} type Studnt struct {
name string
age int
} //实现了sayHello
func (tmp *Studnt) sayHello() {
fmt.Println("i am student")
} //实现了sing
func (tmp *Studnt) sing(lrc string) {
fmt.Println(lrc)
} func main() {
//定义一个接口类型变量
var per persion
s := &Studnt{"break", }
per = s per.sayHello() //继承过来的接口
per.sing("la la la") //超集可以转化为子集,反过来不行
var h humaner
h = per
h.sayHello() //空接口 实际上就是一个万能类型, 可以保存任意类型值
var i interface{} =
fmt.Println(i)
i = "abc"
fmt.Println(i) //类型断言
if value, ok := i.(string); ok == true {
fmt.Println(value)
} i = Studnt{"break", }
if value, ok := i.(Studnt); ok == true {
fmt.Println(value.name)
} switch i.(type) {
case Studnt:
fmt.Println("Studnt")
case int:
fmt.Println("int")
} }
反射例子
type Student struct {
Name string
Age int
Score float32
} func test(b interface{}) {
t := reflect.TypeOf(b)
fmt.Println(t) v := reflect.ValueOf(b)
k := v.Kind()
fmt.Println(k) iv := v.Interface()
stu, ok := iv.(Student)
if ok {
fmt.Printf("%v %T\n", stu, stu)
}
} func TestStruct(a interface{}) {
tye := reflect.TypeOf(a)
val := reflect.ValueOf(a)
kd := val.Kind()
if kd != reflect.Ptr && val.Elem().Kind() == reflect.Struct {
fmt.Println("expect struct")
return
} num := val.Elem().NumField()
val.Elem().Field().SetString("stu1000")
for i := ; i < num; i++ {
fmt.Printf("**%d %v\n", i, val.Elem().Field(i).Kind())
} fmt.Printf("struct has %d fields\n", num) tag := tye.Elem().Field().Tag.Get("json")
fmt.Printf("tag=%s\n", tag) numOfMethod := val.Elem().NumMethod()
fmt.Printf("struct has %d methods\n", numOfMethod)
var params []reflect.Value
val.Elem().Method().Call(params)
} test(a)
TestStruct(a)

最新文章

  1. (转)REDIS各项配置参数介绍
  2. Web服务器控件之button
  3. 使用私有Pod Spec的类库--提高公司开发效率
  4. 在 Linux 下搭建 Git 服务器
  5. ngRoute AngularJs自带的路由
  6. 靶形数独(codevs 1174)
  7. git bash中避免在push时反复输入用户名和密码
  8. ASCII码、base64编码 为什么有的代码要用 base64 进行编码?
  9. Django的安装配置和开发
  10. vim 模式基础操作
  11. sql数据导出导入格式化
  12. 笔记整理——使用openssl编程
  13. Python之数据结构基础
  14. Android 控件背景选择图片还是drawable XML资源
  15. ubuntu 16.04 python版本切换(python2和python3)
  16. svn 基础
  17. TCP/IP 详解
  18. 转载:Systemd 命令
  19. css中width和padding-top实现正方形
  20. lodash用法系列(2),处理对象

热门文章

  1. Elastic Stack 笔记(六)Elasticsearch5.6 搜索详解
  2. DirectX12 3D 游戏开发与实战第三章内容
  3. input和btton的相互使用————小程序
  4. Day 25 网络基础
  5. 04: OpenGL ES 基础教程03 纹理
  6. UVM——寄存器模型相关的一些函数
  7. 程序员写 2000 行 if else?领导:这个锅我不背
  8. aapt的具体使用
  9. Spring MVC-从零开始-EL(未完待续)
  10. thymeleaf 遍历使用案例