Go基础之--接口
定义
在Go语言中,一个类只要实现了接口要求的所有函数,我们就说这个类实现了该接口
interface类型可以定义一组方法,用来表示一个对象的行为特征,interface不能包含任何变量,接口是引用类型。
举个简单的例子,一个动物的接口,动物有吃的能力,有叫的能力,等等,这里省略,假如动物就只有吃和叫的能力。
package main
import "fmt"
type Animal interface {
Eat()
Talk()
}
type Dog struct{
}
func (d *Dog) Eat(){
fmt.Println("dog eating.....")
}
func (d *Dog) Talk(){
fmt.Println("dog talking....")
}
type Cat struct{
}
func (d *Cat) Eat(){
fmt.Println("cat eating.....")
}
func (d *Cat) Talk(){
fmt.Println("cat talking....")
}
func main(){
var d Dog
var a Animal
a = &d
a.Eat()
a.Talk()
var c Cat
a = &c
a.Eat()
a.Talk()
}
上面这个例子中,Cat和Dog实现了Animal的所有方法,所以Cat和Dog都是动物
小结一下:
Go中的接口不需要显示的实现,只要一个对象实现了接口类型中的所有方法,那么这个对象就实现了这个接口,当然如果一个对象实现了多个interface类型的方法,那么这个对象就实现了多个接口
用于理解接口的一个例子
我们都知道现在的手机有很多支付方式,如:微信支付,支付宝支付,银联支付等等,这里可以通过一个实现支付接口的例子来理解接口
// 定义一个支付的接口
type Pay interface {
pay(userId int64,money float32) error
} // 这里定义一个struct
type AliPay struct { }
// 这里给AliPay添加一个支付方法,实现了Pay接口中的pay方法
func (a *AliPay) pay(userId int64,money float32) error{
fmt.Println("1.连接到阿里支付的服务器")
fmt.Println("2.连接到对应的用户")
fmt.Println("3.检查余额")
fmt.Println("4.扣钱")
fmt.Println("5.返回支付是否成功") return nil
} // 微信支付
type WeChatPay struct { } // 这里也是实现了Pay接口中的pay方法
func (w *WeChatPay) pay(userId int64,money float32) error{
fmt.Println("1.连接到微信支付的服务器")
fmt.Println("2.连接到对应的用户")
fmt.Println("3.检查余额")
fmt.Println("4.扣钱")
fmt.Println("5.返回支付是否成功") return nil
} // 这里定义一个手机struct,并通过字典方式存储自己开通的支付方式
type Phone struct {
PayMap map[string]Pay
} func (p *Phone) OpenWeChatPay(){
weChatPay := &WeChatPay{}
p.PayMap["weChatPay"] = weChatPay
} func (p *Phone) OpenAliPay(){
AliPay := &AliPay{}
p.PayMap["aLiPay"] = AliPay
} func (p *Phone) PayMoney(name string,money float32)(err error){
pay,ok:= p.PayMap[name]
if !ok{
err = fmt.Errorf("不支持【%s】支付方式",name)
return
}
err = pay.pay(1024,money)
return
} func main(){
// 这里切记 字典类型的数据是需要初始化的
phone := &Phone{
PayMap:make(map[string]Pay,10),
} // 这里是用于开通自己有哪些支付方式
//phone.OpenWeChatPay()
phone.OpenAliPay() err := phone.PayMoney("weChatPay",100)
if err != nil{
// 如果微信支付失败了,用支付宝支付
fmt.Printf("支付失败,失败原因:%v\n",err)
fmt.Println("使用支付宝支付")
err = phone.PayMoney("aLiPay",100)
if err != nil{
fmt.Printf("支付失败,失败原因:%v\n",err)
return
}
}
fmt.Println("支付成功,欢迎再次光临")
}
当然可以把上面中关于开通支付方式的两个方法,用一个通用的方法实现,如:
func (p *Phone) OpenPay(name string,pay Pay){
// 可以把上面两个方法更改为这一个方法
p.PayMap[name] = pay
}
空接口
空接口没有任何方法,所有的类型都实现了空接口,空接口什么类型都可以存,如下例子:
package main
import "fmt"
func main() {
// 通过这个例子我们可以发现我们定义的一个空接口可以存任何类型的变量
var a interface{}
var b int = 10
a = b
fmt.Println(a)
var c string = "hello"
a = c
fmt.Println(a)
}
接口的嵌套
一个接口可以嵌套在另外的接口里面,同时一个接口也可以嵌套多个接口
通过下面的例子来理解接口嵌套的概念
package main import "fmt" // 这里定义一个Eater接口
type Eater interface {
Eat()
} // 这里定义一个Talker接口
type Talker interface {
Talk()
} // 这里定义个动物的接口,同时嵌套了Eater和Talker接口
type Animal interface {
Eater
Talker
} // 这里定义一个Dog的struct,并实现talk方法和eat方法,这样就实现了动物的接口
type Dog struct { } func (d *Dog) Talk(){
fmt.Println("talk....")
} func (d *Dog) Eat(){
fmt.Println("eating....")
} func main() {
d := &Dog{}
var a Animal
a = d
a.Eat()
a.Talk()
}
类型断言
如果我们反向想要知道这个接口变量里面实际存储的是哪个类型的对象,可以用下面方法:
通过下面这个例子理解:
package main import (
"fmt"
) type Animal interface {
Eat()
Talk()
} type Dog struct{ } func (d *Dog) Eat(){
fmt.Println("dog eating.....")
} func (d *Dog) Talk(){
fmt.Println("dog talking....")
} type Cat struct{ } func (c *Cat) Eat(){
fmt.Println("cat eating.....")
} func (c *Cat) Talk(){
fmt.Println("cat talking....")
} func justify(a Animal){
// 进行强制转换,如果转换失败则提示错误
dog,ok := a.(*Dog)
if !ok{
fmt.Println("convert to dog failed")
return
}
dog.Eat()
} func main() {
// 分别实例化一个Dog和Cat,并通过justify来进行判断
d := &Dog{}
var a Animal
a = d
a.Eat()
justify(a) c := &Cat{}
a = c
justify(a)
}
再写一个例子,用于判断函数中传入的参数的类型:
package main import (
"fmt"
)
// 这里通过...interface{}表示传入的是可变参数
func justify(items ...interface{}){
for index,v := range items{
//v.(type)表示获取变量的类型
switch v.(type){
case int:
fmt.Printf("第%d个参数is int\n",index)
case float32:
fmt.Printf("第%d个参数is float32\n",index)
case string:
fmt.Printf("第%d个参数is string\n",index)
}
}
} func main() {
var a float32
var b string
var c int
justify(a,b,c)
}
关于猫和狗代码例子中justify方法还可以更改为:
func justify2(a Animal){
switch t:=a.(type){
case *Dog:
t.Eat()
fmt.Printf("t is Dog\n")
case *Cat:
t.Eat()
fmt.Printf("t is Cat\n")
}
}
判断一个变量是否实现了指定的接口
在最开始的时候写了一个关于理解接口的例子,如果我们现在想要判断一个变量是否实现了指定的支付的接口,可以通过如下代码实现
weChat := &WeChatPay{}
// 这里需要一个空接口
var tmp interface{} = weChat
_,ok := tmp.(Pay)
if ok{
fmt.Println("weChat is implement Pay interface")
}
Go基础之--接口的更多相关文章
- 速战速决 (4) - PHP: 类基础, 抽象类, 接口, trait
[源码下载] 速战速决 (4) - PHP: 类基础, 抽象类, 接口, trait 作者:webabcd 介绍速战速决 之 PHP 类基础 抽象类 接口 trait 示例1.类的相关知识点 1(基础 ...
- [.net 面向对象编程基础] (16) 接口
[.net 面向对象编程基础] (16) 接口 关于“接口”一词,跟我们平常看到的电脑的硬件“接口”意义上是差不多的.拿一台电脑来说,我们从外面,可以看到他的USB接口,COM接口等,那么这些接口的目 ...
- spring中基础核心接口总结
spring中基础核心接口总结理解这几个接口,及其实现类就可以快速了解spring,具体的用法参考其他spring资料 1.BeanFactory最基础最核心的接口重要的实现类有:XmlBeanFac ...
- Go语言基础之接口
Go语言基础之接口 接口(interface)定义了一个对象的行为规范,只定义规范不实现,由具体的对象来实现规范的细节. 接口 接口介绍 在Go语言中接口(interface)是一种类型,一种抽象的类 ...
- C#基础--类/接口/成员修饰符,多态、重载、重写,静态和非静态
C#基础--类/接口/成员修饰符,多态.重载.重写,静态和非静态 类/接口/成员修饰符 C#修饰符---接口: 接口默认访问符是internal接口的成员默认访问修饰符是public C#修饰符--类 ...
- Java基础十--接口
Java基础十--接口 一.接口的定义和实例 /* abstract class AbsDemo { abstract void show1(); abstract void show2(); } 8 ...
- Java基础-面向接口(interface)编程
Java基础-面向接口(interface)编程 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.接口的概念 接口是功能的集合,同样可看做是一种数据类型,是比抽象类更为抽象的“类 ...
- GO学习-(14) Go语言基础之接口
Go语言基础之接口 接口(interface)定义了一个对象的行为规范,只定义规范不实现,由具体的对象来实现规范的细节. 接口 接口类型 在Go语言中接口(interface)是一种类型,一种抽象的类 ...
- C#夯实基础之接口(《CLR via C#》读书笔记)
一. 接口的类型 接口是引用类型.因此从值类型赋值给接口是需要装箱的.如下所示: class Program { static void Main(string[] args) { ISay catS ...
- Java基础10 接口的继承与抽象类
链接地址:http://www.cnblogs.com/vamei/archive/2013/03/31/2982240.html 作者:Vamei 出处:http://www.cnblogs.com ...
随机推荐
- c++2(循环和递归)
其实编程的朋友知道,不管学什么语言,循环和递归是两个必须学习的内容.当然,如果循环还好理解一点,那么递归却没有那么简单.我们曾经对递归讳莫如深,但是我想告诉大家的是,递归其实没有那么可怕.所谓的递归就 ...
- git工作流程一览
Git是分布式版本控制系统,没有中央服务器,每个人的电脑就是一个完整的版本库,工作的时候不需要联网了,因为版本都在自己电脑上.协同的方法是这样的:比如说自己在电脑上改了文件A,其他人也在电脑上改了文件 ...
- 你必须知道的session与cookie
Session本质 提到Session我们能联想到的就是用户登录功能,而本身我们使用Session的基础是通过url进行访问的,也就是使用http协议进行访问的,而http协议本身是无状态的,那么问题 ...
- [国嵌攻略][164][USB驱动程序设计]
USB驱动模型 1.USB host controller driver(主控器驱动):为USB主控制器提供驱动程序 2.USB core(USB核心):连接USB主控制器驱动和USB设备驱动 3.U ...
- 关于jquery ajax跨域请求获取response headers问题
背景:最近项目jwt用户认证方式,关于jwt本人就不再赘述,大家可自行百度. jwt token基本流程是这样的: 用户使用用户名密码来请求服务器 服务器进行验证用户的信息 服务器通过验证发送给用户一 ...
- tp5 $_ENV获取不到数据
$_ENV变量是取决于服务器的环境变量的,从不同的服务器上获取的$_ENV变量打印出的结果可能是不同的. php的配置文件php.ini的配置项为:variables_order = "GP ...
- CSS3 background-size 属性
定义和用法 background-size 属性规定背景图像的尺寸. 默认值: auto 继承性: no 版本: CSS3 JavaScript 语法: object.style.background ...
- PHP defined() 函数
定义和用法 defined() 函数检查某常量是否存在. 若常量存在,则返回 true,否则返回 false. 语法 defined(name) 参数 描述 name 必需.规定要检查的常量的名称. ...
- AVFrame转换到Mat,yuv420p转换到RGB源代码
FFmpeg中AVFrame到OpenCV中Mat的两种转换方法 方法一:查表法 void AVFrame2Img(AVFrame *pFrame, cv::Mat& img) { int f ...
- Oracle内连接、外连接、右外连接、全外连接小总结
数据库版本:Oracle 9i 表TESTA,TESTB,TESTC,各有A, B两列 A B 001 10A 002 20A A B 001 10B 003 30B A B 001 10C 004 ...