一、概念
1、 面向对象语言中,接口用于定义对象的行为。接口只指定对象应该做什么,实现这种行为的方法(实现细节)是由对象来决定。
2、 在Go语言中,接口是一组方法签名。

  • •接口只指定了类型应该具有的方法,类型决定了如何实现这些方法。
  • •当某个类型为接口中的所有方法提供了具体的实现细节时,这个类型就被称为实现了该接口。
  • •接口定义了一组方法,如果某个对象实现了该接口的所有方法,则此对象就实现了该接口。

3、 Go语言的类型都是隐式实现接口的。任何定义了接口中所有方法的类型都被称为隐式地实现了该接口。

二、接口的使用

go没有 implements, extends 关键字,其实这种编程语言叫做duck typing编程语言。

package main

import "fmt"
import "base" //定义接口
type Phone interface {
call()
} type AndroidPhone struct {
} type IPhone struct {
} func (a AndroidPhone) call() {
fmt.Println("我是安卓手机,可以打电话了")
} func (i IPhone) call() {
fmt.Println("我是苹果手机,可以打电话了")
} func main() {
// 定义接口类型的变量
var phone Phone
//phone = new(AndroidPhone)
phone = AndroidPhone{}
fmt.Printf("%T , %v , %p \n" , phone , phone , &phone)
phone.call() //phone = new(IPhone)
phone = IPhone{}
fmt.Printf("%T , %v , %p \n" , phone , phone , &phone)
phone.call()
}

 动态类型与静态类型语言

  • •动态类型的好处很多,Python代码写起来很快。但是缺陷也是显而易见的:错误往往要在运行时才能被发现。
  • •相反,静态类型语言往往在编译时就是发现这类错误:如果某个变量的类型没有显式声明实现了某个接口,那么,这个变量就不能用在要求一个实现了这个接口的地方。

 Go类型系统采取了折中的办法:
•之所以说这是一种折中的办法,原因如下:

  • 〇第一,结构体类型T不需要显式地声明它实现了接口 I。只要类型T实现了接口1规定的所有方法,它就自动地实现了接口 I。这样就像动态语言一样省了很多代码,少了许多限制。
  • 〇第二,将结构体类型的变量显式或者隐式地转换为接口 I类型的变量i。这样就可以和其它静态类型语言一样,在编译时检查参数的合法性。

三、多态

•事物的多种形态

  • • Go中的多态性是在接口的帮助下实现的。定义接口类型,仓U建实现该接口的结构体对象。
  • •定义接口类型的对象,可以保存实现该接口的任何类型的值。Go语言接口变量的这个特性实现了 Go语言中的多态性。
  • •接口类型的对象,不能访问其实现类中的属性字段。
package main

import "fmt"
import "base" type Income interface {
calculate() float64 //计算收入总额
source() string //用来说明收入来源
} //固定账单项目
type FixedBilling struct {
projectName string //工程项目
biddedAmount float64 //项目招标总额
} //定时生产项目(定时和材料项目)
type TimeAndMaterial struct {
projectName string
workHours float64 //工作时长
hourlyRate float64 //每小时工资率
} //固定收入项目
func (f FixedBilling) calculate() float64 {
return f.biddedAmount
} func (f FixedBilling) source() string {
return f.projectName
} //定时收入项目
func (t TimeAndMaterial) calculate() float64 {
return t.workHours * t.hourlyRate
} func (t TimeAndMaterial) source() string {
return t.projectName
} //通过广告点击获得收入
type Advertisement struct {
adName string
clickCount int
incomePerclick float64
} func (a Advertisement) calculate() float64 {
return float64(a.clickCount) * a.incomePerclick
} func (a Advertisement) source() string {
return a.adName
} func main() {
p1 := FixedBilling{"项目1", }
p2 := FixedBilling{"项目2", }
p3 := TimeAndMaterial{"项目3", , }
p4 := TimeAndMaterial{"项目4", , }
p5 := Advertisement{"广告1", , 0.1}
p6 := Advertisement{"广告2", , 0.05} ic := []Income{p1, p2, p3, p4, p5, p6}
fmt.Println("total=",calculateNetIncome(ic))
} //计算净收入
func calculateNetIncome(ic []Income) float64 {
netincome := 0.0
for _, income := range ic {
fmt.Printf("收入来源:%s ,收入金额:%.2f \n", income.source(), income.calculate())
netincome += income.calculate()
}
return netincome
}

四、空接口

•空接口 :该接口中没有任何的方法。任意类型都可以实现该接口。
•空interface这样定义:interface{},也就是包含0个method的interface。
•用空接口表示任意数据类型。类似于java中的object。
•空接口常用于以下情形:
〇 1、println的参数就是空接口
〇 2、定义一个map: key是string,value是任意数据类型
〇 3、定义一个切片,其中存储任意类型的数据

package main

import (
"fmt"
) type A interface {
} type Cat struct {
name string
age int
} type Person struct {
name string
sex string
} func main() {
var a1 A = Cat{"Mimi", }
var a2 A = Person{"Steven", "男"}
var a3 A = "Learn golang with me!"
var a4 A =
var a5 A = 3.14 showInfo(a1)
showInfo(a2)
showInfo(a3)
showInfo(a4)
showInfo(a5)
fmt.Println("------------------") //1、fmt.println参数就是空接口
fmt.Println("println的参数就是空接口,可以是任何数据类型", , 3.14, Cat{"旺旺", }) //2、定义map。value是任何数据类型
map1 := make(map[string]interface{})
map1["name"] = "Daniel"
map1["age"] =
map1["height"] = 1.71
fmt.Println(map1)
fmt.Println("------------------") // 3、定义一个切片,其中存储任意数据类型
slice1 := make([]interface{}, , )
slice1 = append(slice1, a1, a2, a3, a4, a5)
fmt.Println(slice1) transInterface(slice1) //var cat1 A = Cat{"MiaoMiao" , 3}
//fmt.Println(cat1.name , cat1.age) } //接口对象转型
//接口对象.(type),配合switch...case语句
func transInterface(s []interface{}) {
for i := range s {
fmt.Println("第", i+ , "个数据:")
switch t := s[i].(type) {
case Cat:
fmt.Printf("\t Cat对象,name属性:%s,age属性:%d \n" , t.name , t.age)
case Person:
fmt.Printf("\t Person对象,name属性:%s,sex属性:%s \n" , t.name , t.sex)
case string:
fmt.Println("\t string类型" , t)
case int:
fmt.Println("\t int类型" , t)
case float64:
fmt.Println("\t float64类型" , t)
}
}
} func showInfo(a A) {
fmt.Printf("%T , %v \n", a, a)
}

五、接口对象转型
1、 方式一:
• instance, ok :=接口对象.(实际类型)
•如果该接口对象是对应的实际类型,那么instance就是转型之后对象,ok的值为true
•配合if... else if...语句使用
2、 方式二:
•接口对象.(type)
•配合switch...case语句使用

package main

import "fmt"
import (
"base"
"math"
) //1、定义接口
type Shape interface {
perimeter() float64
area() float64
} //2.矩形
type Rectangle struct {
a, b float64
} //3.三角形
type Triangle struct {
a, b, c float64
} //4.圆形
type Circle struct {
radius float64
} //定义实现接口的方法
func (r Rectangle) perimeter() float64 {
return (r.a + r.b) *
} func (r Rectangle) area() float64 {
return r.a * r.b
} func (t Triangle) perimeter() float64 {
return t.a + t.b + t.c
} func (t Triangle) area() float64 {
//海伦公式
p := t.perimeter() / //半周长
return math.Sqrt(p * (p - t.a) * (p - t.b) * (p - t.c))
} func (c Circle) perimeter() float64 {
return * math.Pi * c.radius
} func (c Circle) area() float64 {
return math.Pow(c.radius, ) * math.Pi
} //接口对象转型方式1
//instance,ok := 接口对象.(实际类型)
func getType(s Shape) {
if instance, ok := s.(Rectangle); ok {
fmt.Printf("矩形:长度%.2f , 宽度%.2f , ", instance.a, instance.b)
} else if instance, ok := s.(Triangle); ok {
fmt.Printf("三角形:三边分别:%.2f , %.2f , %.2f , ", instance.a, instance.b, instance.c)
} else if instance, ok := s.(Circle); ok {
fmt.Printf("圆形:半径%.2f , ", instance.radius)
}
} //接口对象转型——方式2
//接口对象.(type), 配合switch和case语句使用
func getType2(s Shape) {
switch instance := s.(type) {
case Rectangle:
fmt.Printf("矩形:长度为%.2f , 宽为%.2f ,\t", instance.a, instance.b)
case Triangle:
fmt.Printf("三角形:三边分别为%.2f ,%.2f , %.2f ,\t", instance.a, instance.b, instance.c)
case Circle:
fmt.Printf("圆形:半径为%.2f ,\t", instance.radius)
}
} func getResult(s Shape) {
getType2(s)
fmt.Printf("周长:%.2f ,面积:%.2f \n", s.perimeter(), s.area())
} func main() {
var s Shape
s = Rectangle{, }
getResult(s)
showInfo(s) s = Triangle{, , }
getResult(s)
showInfo(s) s = Circle{}
getResult(s)
showInfo(s) x := Triangle{, , }
fmt.Println(x) } func (t Triangle) String() string {
return fmt.Sprintf("Triangle对象,属性分别为:%.2f, %.2f, %.2f", t.a, t.b, t.c)
} func showInfo(s Shape) {
fmt.Printf("%T ,%v \n", s, s)
fmt.Println("-------------------")
}

GO基础之接口的更多相关文章

  1. 速战速决 (4) - PHP: 类基础, 抽象类, 接口, trait

    [源码下载] 速战速决 (4) - PHP: 类基础, 抽象类, 接口, trait 作者:webabcd 介绍速战速决 之 PHP 类基础 抽象类 接口 trait 示例1.类的相关知识点 1(基础 ...

  2. [.net 面向对象编程基础] (16) 接口

    [.net 面向对象编程基础] (16) 接口 关于“接口”一词,跟我们平常看到的电脑的硬件“接口”意义上是差不多的.拿一台电脑来说,我们从外面,可以看到他的USB接口,COM接口等,那么这些接口的目 ...

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

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

  4. Go语言基础之接口

    Go语言基础之接口 接口(interface)定义了一个对象的行为规范,只定义规范不实现,由具体的对象来实现规范的细节. 接口 接口介绍 在Go语言中接口(interface)是一种类型,一种抽象的类 ...

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

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

  6. Java基础十--接口

    Java基础十--接口 一.接口的定义和实例 /* abstract class AbsDemo { abstract void show1(); abstract void show2(); } 8 ...

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

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

  8. GO学习-(14) Go语言基础之接口

    Go语言基础之接口 接口(interface)定义了一个对象的行为规范,只定义规范不实现,由具体的对象来实现规范的细节. 接口 接口类型 在Go语言中接口(interface)是一种类型,一种抽象的类 ...

  9. C#夯实基础之接口(《CLR via C#》读书笔记)

    一. 接口的类型 接口是引用类型.因此从值类型赋值给接口是需要装箱的.如下所示: class Program { static void Main(string[] args) { ISay catS ...

  10. Java基础10 接口的继承与抽象类

    链接地址:http://www.cnblogs.com/vamei/archive/2013/03/31/2982240.html 作者:Vamei 出处:http://www.cnblogs.com ...

随机推荐

  1. js中动画原理

    现如今,许多页面上均有一些动画效果.适当的动画效果可以在一定程度上提高页面的美观度,具有提示效果的动画可以增强页面的易用性. 实现页面动画的途径一般有两种. 一种是通过操作JavaScript间接操作 ...

  2. 【并发技术16】线程同步工具Exchanger的使用

    如果两个线程在运行过程中需要交换彼此的信息,比如一个数据或者使用的空间,就需要用到 Exchanger 这个类,Exchanger 为线程交换信息提供了非常方便的途径,它可以作为两个线程交换对象的同步 ...

  3. 为什么说 Java 中只有值传递?

    对于初学者来说,要想把这个问题回答正确,是比较难的.在第二天整理答案的时候,我发现我竟然无法通过简单的语言把这个事情描述的很容易理解,遗憾的是,我也没有在网上找到哪篇文章可以把这个事情讲解的通俗易懂. ...

  4. ARTS-S c++调用pytorch接口

    想跑通第1个参考资料上讲的例子,一定要注意gcc和gperftools的版本.因为LibTorch用了c++17的over-aligned新特性. centos默认的gcc是4.8.5不支持这个新特性 ...

  5. 在5分钟内将Spring Boot作为Windows服务启动

    分享优锐课学习笔记~来看一下如何使用Spring Boot创建Windows服务以及通过配置详细信息来快速启动并运行. 最近不得不将Spring Boot应用程序部署为Windows服务,感到惊讶的是 ...

  6. 关于《iBoard 电子学堂》的学习及进阶方式(精 转)

    关于<iBoard 电子学堂>的学习及进阶方式 <iBoard 电子学堂>自发布以来,受到广大网友的热烈关注.虽然我前期设计我花了大量精力,但能得到大家的认可,我也非常欣慰.由 ...

  7. iOS开发 为何 大不如前?原因竟然是这个?

    前言: 近期,社会上对iOS开发行业的负面信息越来越多,并且还被一些黑骗机构的胡诌八扯越描越黑,现在iOS开发按照开发者与公司招聘的数量上来看,是显示的供大于求,但是从各公司的招人计划上来看,明显是供 ...

  8. Python3 函数进阶1

    目录 闭包函数 什么是闭包函数 闭包函数的作用 装饰器 什么是装饰器 无参装饰器 有参装饰器 闭包函数 什么是闭包函数 闭包函数本质上就是函数嵌套和高阶函数 闭包函数的满足条件: 必须嵌套函数 内嵌函 ...

  9. cookie、session和token那些事

    cookie 和 session 众所周知,HTTP 是一个无状态协议,所以客户端每次发出请求时,下一次请求无法得知上一次请求所包含的状态数据,如何能把一个用户的状态数据关联起来呢? 比如在淘宝的某个 ...

  10. 各大中间件底层技术-分布式一致性协议 Raft 详解

    前言 正式介绍 Raft 协议之前,我们先来举个职场产研团队的一个例子