一、接口(interfaces)
1、概述

接口定义了一组方法(方法集),但是这些方法不包含(实现)代码:它们没有被实现(它们是抽象的)。接口里也不能包含变量。

通过如下格式定义接口:

type Namer interface {
Method1(param_list) return_type
Method2(param_list) return_type

}

类型不需要显式声明它实现了某个接口:接口被隐式地实现。多个类型可以实现同一个接口。
实现某个接口的类型(除了实现接口方法外)可以有其他的方法。
一个类型可以实现多个接口。
接口类型可以包含一个实例的引用, 该实例的类型实现了此接口(接口是动态类型)。

2、例子:
package mainimport "fmt"type Shaper interface {Area() float32
}type Square struct {side float32
}func (sq *Square) Area() float32 {return sq.side * sq.side
}func main() {sq1 := new(Square)sq1.side = 5var areaIntf ShaperareaIntf = sq1// shorter,without separate declaration:// areaIntf := Shaper(sq1)// or even:// areaIntf := sq1fmt.Printf("The square has area: %f\n", areaIntf.Area())
}

输出:

The square has area: 25.000000

上面的程序定义了一个结构体 Square 和一个接口 Shaper,接口有一个方法 Area()。

3、 接口嵌套

接口嵌套接口
一个接口可以包含一个或多个其他的接口,这相当于直接将这些内嵌接口的方法列举在外层接口中一样。

比如接口 File 包含了 ReadWrite 和 Lock 的所有方法,它还额外有一个 Close() 方法。

type ReadWrite interface {Read(b Buffer) boolWrite(b Buffer) bool
}type Lock interface {Lock()Unlock()
}type File interface {ReadWriteLockClose()
}
4、 类型断言:如何检测和转换接口变量的类型
if v, ok := varI.(T); ok {  // checked type assertionProcess(v)return
}if _, ok := varI.(T); ok {// ...
}

varI 必须是一个接口变量,否则编译器会报错:invalid type assertion: varI.(T) (non-interface type (type of varI) on left)

5、 类型判断:type-switch
switch t := areaIntf.(type) {case *Square:fmt.Printf("Type Square %T with value %v\n", t, t)
case *Circle:fmt.Printf("Type Circle %T with value %v\n", t, t)
case nil:fmt.Printf("nil value: nothing to check?\n")
default:fmt.Printf("Unexpected type %T\n", t)
}//仅仅是测试变量的类型,不用它的值,那么就可以不需要赋值语句,比如:switch areaIntf.(type) {case *Square:// TODO
case *Circle:// TODO
...
default:// TODO
}
6、 测试一个值是否实现了某个接口

假定 v 是一个值,然后我们想测试它是否实现了 Stringer 接口,可以这样做:

type Stringer interface {String() string
}if sv, ok := v.(Stringer); ok {fmt.Printf("v implements String(): %s\n", sv.String()) // note: sv, not v
}
7、使用方法集与接口

总结

在接口上调用方法时,必须有和方法定义时相同的接收者类型或者是可以从具体类型 P 直接可以辨识的:

指针方法可以通过指针调用
值方法可以通过值调用
接收者是值的方法可以通过指针调用,因为指针会首先被解引用
接收者是指针的方法不可以通过值调用,因为存储在接口中的值没有地址
将一个值赋值给一个接口时,编译器会确保所有可能的接口方法都可以在此值上被调用,
因此不正确的赋值在编译期就会失败。

Go 语言规范定义了接口方法集的调用规则:

类型 *T 的可调用方法集包含接受者为 *T 或 T 的所有方法集
类型 T 的可调用方法集包含接受者为 T 的所有方法
类型 T 的可调用方法集不包含接受者为 *T 的方法
8、空接口
type Any interface {}

通过空接口测试变量类型

package mainimport "fmt"type specialString stringvar whatIsThis specialString = "hello"func TypeSwitch() {testFunc := func(any interface{}) {switch v := any.(type) {case bool:fmt.Printf("any %v is a bool type", v)case int:fmt.Printf("any %v is an int type", v)case float32:fmt.Printf("any %v is a float32 type", v)case string:fmt.Printf("any %v is a string type", v)case specialString:fmt.Printf("any %v is a special String!", v)default:fmt.Println("unknown type!")}}testFunc(whatIsThis)
}func main() {TypeSwitch()
}

输出:

any hello is a special String!
二、反射包 reflect

反射是用程序检查其所拥有的结构,尤其是类型的一种能力;这是元编程的一种形式。反射可以在运行时检查类型和变量,例如它的大小、方法和 动态 的调用这些方法。
reflect.TypeOf 和 reflect.ValueOf,返回被检查对象的类型和值。

Kind():反射可以从接口值反射到对象,也可以从对象反射回接口值。

v:=reflect.ValueOf(x),那么 v.Kind() 返回 reflect.Float64
Kind 总是返回底层类型:
type MyInt int
var m MyInt = 5
v := reflect.ValueOf(m)
方法 v.Kind() 返回 reflect.Int。
CanSet():
Elem():
SetFloat():
有些时候需要反射一个结构类型。NumField() 方法返回结构内的字段数量;通过一个 for 循环用索引取得每个字段的值 Field(i)。

空接口和函数重载
在 Go 语言中函数重载可以用可变参数 …T 作为函数最后一个参数来实现。
如果我们把 T 换为空接口,那么可以知道任何类型的变量都是满足 T (空接口)类型的,这样就允许我们传递任何数量任何类型的参数给函数,即重载的实际含义。

函数 fmt.Printf 就是这样做的:

fmt.Printf(format string, a ...interface{}) (n int, errno error)
三、总结:Go 中的面向对象

我们总结一下前面看到的:Go 没有类,而是松耦合的类型、方法对接口的实现。
OO 语言最重要的三个方面分别是:封装,继承和多态,在 Go 中它们是怎样表现的呢?
封装(数据隐藏):和别的 OO 语言有 4 个或更多的访问层次相比,Go 把它简化为了 2 层:

1)包范围内的:通过标识符首字母小写,对象 只在它所在的包内可见
2)可导出的:通过标识符首字母大写,对象 对所在包以外也可见

类型只拥有自己所在包中定义的方法。

继承:用组合实现:内嵌一个(或多个)包含想要的行为(字段和方法)的类型;多重继承可以通过内嵌多个类型实现
多态:用接口实现:某个类型的实例可以赋给它所实现的任意接口类型的变量。类型和接口是松耦合的,并且多重继承可以通过实现多个接口实现。Go 接口不是 Java 和 C# 接口的变体,而且接口间是不相关的,并且是大规模编程和可适应的演进型设计的关键。

【Go】Go基础(九):接口(Interfaces)与反射(reflection)相关推荐

  1. JAVA常用基础知识点[继承,抽象,接口,静态,枚举,反射,泛型,多线程...]

    类的继承 Java只支持单继承,不允许多重继承 - 一个子类只能有一个父类 - 一个父类可以派生出多个子类 这里写图片描述 子类继承了父类,就继承了父类的方法和属性. 在子类中,可以使用父类中定义的方 ...

  2. JAVA常用基础知识点[继承,抽象,接口,静态,枚举,反射,泛型,多线程.]

    类的继承 Java只支持单继承,不允许多重继承  - 一个子类只能有一个父类  - 一个父类可以派生出多个子类    子类继承了父类,就继承了父类的方法和属性.  在子类中,可以使用父类中定义的方法和 ...

  3. Java基础-面向接口(interface)编程

    Java基础-面向接口(interface)编程 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.接口的概念 接口是功能的集合,同样可看做是一种数据类型,是比抽象类更为抽象的&q ...

  4. 基础九大字段改造,解除强依赖数据库设计

    实现视频如下 基础九大字段改造,解除强依赖数据库设计 一直以来,笔者对底层的九大基础字段并不是很满意,从数据写入至字段定义均有瑕疵. 此间,笔者决心改掉这一直以来的错误设计,将其精简为八大常用字段. ...

  5. 反射(reflection)基础

    反射(reflection) 1. 一个需求引出反射 1.1 请看下面的问题 根据配置文件 re.properties 指定信息,创建Cat对象并调用方法hi 我们用之前的方式处理就是: 先创建一个C ...

  6. Struts2中action接收参数的三种方法及ModelDriven跟Preparable接口结合JAVA反射机制的灵活用法...

    Struts2中action接收参数的三种方法及ModelDriven跟Preparable接口结合JAVA反射机制的灵活用法 www.MyException.Cn   发布于:2012-09-15 ...

  7. TypeScript基础入门 - 接口 - 继承接口

    转载地址 TypeScript基础入门 - 接口 - 继承接口 项目实践仓库 https://github.com/durban89/typescript_demo.git tag: 1.0.13 为 ...

  8. spring中基础核心接口总结

    spring中基础核心接口总结 理解这几个接口,及其实现类就可以快速了解spring,具体的用法参考其他spring资料 1.BeanFactory最基础最核心的接口 重要的实现类有: XmlBean ...

  9. C#基础--类/接口/成员修饰符,多态、重载、重写,静态和非静态

    C#基础--类/接口/成员修饰符,多态.重载.重写,静态和非静态 类/接口/成员修饰符 C#修饰符---接口: 接口默认访问符是internal 接口的成员默认访问修饰符是public C#修饰符-- ...

  10. 这样设计是否更好些~仓储接口是否应该设计成基础操作接口和扩展操作接口

    前言 我们进行linq to sql和ef时代后,底层的实现基本使用的是repository模块,即仓储模式,事实上就是把ORM实体的最基本操作进行封闭,对外层不公开操作实现的细节. 面向接口的编程 ...

最新文章

  1. 【MATLAB】矩阵信息的获取
  2. 17岁「天才少女」被8所世界名校录取,最终选择MIT计算机系,还说学成后肯定回国...
  3. android text字体居中显示,Android Canvas的drawText()和文字居中方案
  4. 远程桌面连接mstsc 超扎心
  5. C++生成随机数:高斯/正态分布(gaussian/normal distribution)
  6. JAVA bean与XML互转的利器---XStream
  7. Linux内核管理子系统和进程管理子系统
  8. python实现bt下载器_10行 Python代码使用磁力链接批量下载种子
  9. html2canvas ios 15.0截屏 变黑 页面刷新
  10. JSR303数据校验
  11. 三跨计算机考研学校推荐,考研实现三跨—跨学校,跨地区,跨学科现实吗?
  12. 四川大学计算机学院软件工程期末,2015四川大学软件工程期末复习.doc
  13. 嘟嘟牛app算法hook
  14. IdentityServer4系列(05)【授权方式】
  15. 新建第一个HBuilder项目
  16. 传动系统结构简图_输送带传动结构简图大全
  17. 【JavaScript】按钮绑定点击事件-onCliek事件
  18. jQuery实现QQ分组列表效果
  19. 批处理 删除文件 脚本
  20. 千千静听安卓版是百度音乐旗下一款手机音乐软件,集本地歌曲播放

热门文章

  1. 【camera】3.相机成像颜色及其组成
  2. pytorch量化感知训练(QAT)示例---ResNet
  3. 中秋祝福网页制作_中秋节祝福语不知怎么写?这3个小程序让你的祝福更精美...
  4. 相机标定 matlab opencv ROS三种方法标定步骤(1)
  5. 如何理解Nyquist采样定理?
  6. 写实的CG人物角色制作学习教程
  7. asp.net Core多环境读取Json
  8. centos安装配置nginx,ssl生产和配置教程
  9. EntityFrameworkCore 安装
  10. untitled与前端——初学