【原创】go语言学习(十六)接口
目录
- 接口介绍与定义
- 空接口和类型断言
- 指针接收和值接收区别
- 接口嵌套
接口介绍与定义
1、 接口定义了一个对象的行为规范
A. 只定义规范,不实现
B. 具体的对象需要实现规范的细节
2、Go中接口定义
A. type 接口名字 interface
B. 接口里面是一组方法签名的集合
type Animal interface {
Talk()
Eat() int
Run()
}
3、Go中接口的实现
A. 一个对象只要包含接口中的方法,那么就实现了这个接口
B. 接口类型的变量可以保存具体类型的实例
type Animal interface {
Talk()
Eat() int
Run()
}
4、接口实例
A. 一个公司需要计算所有职员的薪水
B. 每个职员的薪水计算方式不同
package main import (
"fmt"
) type Employer interface {
CalcSalary() float32
} type Programer struct {
name string
base float32
extra float32
} func NewProgramer(name string, base float32, extra float32) Programer {
return Programer{
name: name,
base: base,
extra: extra,
}
} func (p Programer) CalcSalary() float32 {
return p.base
} type Sale struct {
name string
base float32
extra float32
} func NewSale(name string, base, extra float32) Sale {
return Sale{
name: name,
base: base,
extra: extra,
}
} func (p Sale) CalcSalary() float32 {
return p.base + p.extra*p.base*0.5
} func calcALL(e []Employer) float32 {
var cost float32
for _, v := range e {
cost = cost + v.CalcSalary()
} return cost
} func main() {
p1 := NewProgramer("搬砖1", 1500.0, 0)
p2 := NewProgramer("搬砖2", 1500.0, 0)
p3 := NewProgramer("搬砖3", 1500.0, 0) s1 := NewSale("销售1", 800.0, 2.5)
s2 := NewSale("销售2", 800.0, 2.5)
s3 := NewSale("销售3", 800.0, 2.5) var employList []Employer
employList = append(employList, p1)
employList = append(employList, p2)
employList = append(employList, p3) employList = append(employList, s1)
employList = append(employList, s2)
employList = append(employList, s3) cost := calcALL(employList)
fmt.Printf("这个月的人力成本:%f\n", cost) }
5、接口类型变量
A. var a Animal
B. 那么a能够存储所有实现Animal接口的对象实例
package main import "fmt" type Animal interface {
Talk()
Eat()
Name() string
} type Dog struct {
} func (d Dog) Talk() {
fmt.Println("汪汪汪")
} func (d Dog) Eat() {
fmt.Println("我在吃骨头")
} func (d Dog) Name() string {
fmt.Println("我的名字叫旺财")
return "旺财"
} type Pig struct {
} func (d Pig) Talk() {
fmt.Println("坑坑坑")
} func (d Pig) Eat() {
fmt.Println("我在吃草")
} func (d Pig) Name() string {
fmt.Println("我的名字叫八戒")
return "八戒"
} func testInterface1() {
var d Dog
var a Animal
a = d a.Eat()
a.Talk()
a.Name() var pig Pig
a = pig
a.Eat()
a.Talk()
a.Name()
} func just(a Animal) {
// d, ok := a.(Dog)
// p, ok := a.(Pig)
switch v := a.(type) {
case Dog:
fmt.Printf("v is dog, %v\n", v)
case Pig:
fmt.Printf("v is dog, %v\n", v)
default:
fmt.Printf("not support")
}
} func testInterface2() {
var d Dog
just(d)
} func main() {
//testInterface1()
testInterface2()
}
空接口和类型断言
1、空接口
A. 空接口没有定义任何方法
B. 所以任何类型都实现了空接口
interface {
}
package main import "fmt" func describe(a interface{}) {
fmt.Printf("%T %v\n", a, a)
} func testInterface() {
var a interface{}
var b int = 100
a = b fmt.Printf("%T %v\n", a, a) var c string = "hello"
a = c
fmt.Printf("%T %v\n", a, a) var d map[string]int = make(map[string]int, 100)
d["abc"] = 1000
d["eke"] = 30 a = d
fmt.Printf("%T %v\n", a, a)
} type Student struct {
Name string
Sex int
} func main() { a := 65
describe(a) str := "hello"
describe(str) var stu Student = Student{
Name: "user01",
Sex: 1,
} describe(stu)
}
2、类型断言
A. 如何获取接口类型里面存储的具体的值呢?
B.类型断言的坑
C.如何解决,引入 ok判断机制! v, ok := i.(T)
D.type switch。
E.type switch另外一种写法,解决转两次的问题
package main import "fmt" // 类型断言
func test(a interface{}) {
s, ok := a.(int)
if ok {
fmt.Println(s)
return
}
str, ok := a.(string)
if ok {
fmt.Println(str)
return
} f, ok := a.(float32)
if ok {
fmt.Println(f)
return
} fmt.Println("can not define the type of a") } func testInterface1() {
var a int = 100
test(a) var b string = "hello"
test(b)
} // case优雅实现(二次转换)
func testSwitch(a interface{}) {
switch a.(type) {
case string:
fmt.Printf("a is string, value: %v", a.(string))
case int:
fmt.Printf("a is int, value: %v", a.(int))
case int32:
fmt.Printf("a is not, value: %v", a.(int32))
default:
fmt.Println("no support type")
}
} func testInterface2() {
var a int = 100
testSwitch(a) var b string = "hellow"
testSwitch(b)
} // case优雅实现(一次转换)
func testSwitch2(a interface{}) {
switch v := a.(type) {
case string:
fmt.Printf("a is string, value: %v", v)
case int:
fmt.Printf("a is int, value: %v", v)
case int32:
fmt.Printf("a is not, value: %v", v)
default:
fmt.Println("no support type")
}
} func testInterface3() {
var a int = 100
testSwitch2(a) var b string = "hellow"
testSwitch2(b)
} func main() {
testInterface1()
testInterface2()
testInterface3()
}
指针接收和值接收区别
1、指针接收
package main import "fmt" type Animal interface {
Talk()
Eat()
Name() string
} type Dog struct {
} func (d *Dog) Talk() {
fmt.Println("汪汪汪")
} func (d *Dog) Eat() {
fmt.Println("我在吃骨头")
} func (d *Dog) Name() string {
fmt.Println("我的名字叫旺财")
} func main() {
var a Animal
// 值
// a存的是一个值类型的Dog,那么调用a.Eat(). &Dog ->Eat()
// 如果一个变量存储在接口类型的变量中之后,那么不能获取这个变量的地址
//var d Dog
//a = d
//a.Eat()
//
//fmt.Printf("%T %v\n", a, a) // 指针
var d1 *Dog = &Dog{}
a = d1
// *(&Dog).Eat()
a.Eat()
fmt.Printf("*Dog %T %v\n", d1, d1)
}
接口嵌套
1、 实现多接口,同一个类型可以实现多个接口
2、 接口嵌套,和结构体嵌套类似
package main import "fmt" type Animal interface {
Talk()
Eat()
Name() string
} type PuruDongwu interface {
TaiSheng()
} type Dog struct {
} func (d Dog) Talk() {
fmt.Println("汪汪汪")
} func (d Dog) Eat() {
fmt.Println("我在吃骨头")
} func (d Dog) Name() string {
fmt.Println("我的名字叫旺财")
return "旺财"
} func (d Dog) TaiSheng() {
fmt.Println("狗是胎生的")
} func main() {
var d Dog
var a Animal fmt.Printf("%v %T %p", a, a, a) if a == nil {
fmt.Println("a is nil")
} a = d
a.Eat() var b PuruDongwu
b = d
b.TaiSheng()
}
【原创】go语言学习(十六)接口的更多相关文章
- Go语言学习笔记六: 循环语句
Go语言学习笔记六: 循环语句 今天学了一个格式化代码的命令:gofmt -w chapter6.go for循环 for循环有3种形式: for init; condition; increment ...
- 强化学习(十六) 深度确定性策略梯度(DDPG)
在强化学习(十五) A3C中,我们讨论了使用多线程的方法来解决Actor-Critic难收敛的问题,今天我们不使用多线程,而是使用和DDQN类似的方法:即经验回放和双网络的方法来改进Actor-Cri ...
- 【原创】go语言学习(六)函数详解2
目录 变量作用域和可见性 匿名函数 闭包 课后练习 变量作用域和可见性 1.全局变量量,在程序整个生命周期有效. var a int = 10 2.局部变量量,分为两种: 1)函数内定义, 2)语句句 ...
- Dart语言学习(十二) Dart面向对象
Dart作为一种高级语言,支持面向对象的很多特性,并且支持基于mixin的继承方式. 基于mixin的继承方式是指:一个类可以继承自多个父类,相当于其他语言里的多继承. 所有的类都有同一个基类Obje ...
- Dart语言学习(十) Dart流程控制语句
一.条件语句:if.if...elseif.if...elseif...else int score = 95; if (score >=90) { print('优秀'); } else if ...
- C 语言学习 第六次作业总结
本次作业,同学们开始学习函数.通过之前和同学们的沟通,似乎同学们在这里遇到的问题比较多.下面,我先帮同学们整理下函数的相关知识点. 什么是函数 首先,需要明确的是,什么是函数.所谓函数,也就是一段有名 ...
- C语言学习第六章
今天开始尝试改变! 今天要学习函数,一个C语言中的重要组成部分. 首先先聊聊为什么要使用函数?随着学习的深入很多人会发现某段的代码重复使用的几率很大,而如果用一次写一次的话很明显的效率就会比较低,如果 ...
- Go语言学习之7 接口实例、终端文件读写、异常处理
本节主要内容: 1. 终端读写2. 文件读写3. 命令行参数4. Json5. 自定义错误 1. 终端读写 操作终端相关文件句柄常量 os.Stdin:标准输入 os.Stdout:标准输 ...
- GO语言学习(六)Go 语言数据类型
在 Go 编程语言中,数据类型用于声明函数和变量. 数据类型的出现是为了把数据分成所需内存大小不同的数据,编程的时候需要用大数据的时候才需要申请大内存,就可以充分利用内存. Go 语言按类别有以下几种 ...
- Go语言学习笔记(9)——接口类型
接口 Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口. /* 定义接口 */ type interface_name in ...
随机推荐
- CF858F Wizard's Tour
也许更好的阅读体验 \(\mathcal{Description}\) 给定一张 \(n\) 个点 \(m\) 条边的无向图,每条边连接两个顶点,保证无重边自环,不保证连通. 你想在这张图上进行若干次 ...
- 题解-APIO2019路灯
problem \(\mathtt {loj-3146}\) 题意概要:一条直线上有 \(n+1\) 个点和 \(n\) 条道路,每条道路连通相邻两个点.在 \(q\) 个时刻内,每个时刻有如下两种操 ...
- bootstrap栅格系统的container和row一些关系
container有个15px的padding,而我们设定的每个col也都有15px的padding,如果两者直接配合,那么就会产生30px的间距,导致内容和浏览器边框的距离较大,所以用row将所有的 ...
- github的pull request是指什么意思?有什么用处(转)
https://www.cnblogs.com/-walker/p/6093277.html
- 90% 的 Python 开发者不知道的描述符应用
经过上面的讲解,我们已经知道如何定义描述符,且明白了描述符是如何工作的. 正常人所见过的描述符的用法就是上篇文章提到的那些,我想说的是那只是描述符协议最常见的应用之一,或许你还不知道,其实有很多 Py ...
- TensorFlow实现自编码器及多层感知机
1 自动编码机简介 传统机器学习任务在很大程度上依赖于好的特征工程,比如对数值型,日期时间型,种类型等特征的提取.特征工程往往是非常耗时耗力的,在图像,语音和视频中提取到有效的特征就更难 ...
- JDK反编译的两种方式
环境 链接:https://pan.baidu.com/s/1DwWj5Kt4Gfi68k_EOAea_Q 提取码:57j2 apktools+dex2jar+gd-gui 方式一: apktools ...
- 网络调试助手的使用 调试TCP,UDP
网络调试助手是集TCP/UDP服务端客户端一体的网络调试工具,可以帮助网络应用设计.开发.测试人员检查所开发的网络应用软硬件的数据收发状况,提高开发的速度,是TCP/UDP应用开发助手. 集成TCP/ ...
- 直接插入排序算法(java)
直接插入排序是将未排序的数据插入至已排好序序列的合适位置. 具体流程如下: 1.首先比较数组的前两个数据,并排序: 2.比较第三个元素与前两个排好序的数据,并将第三个元素放入适当的位置: 3.比较第四 ...
- 用python批量插入数据到数据库中
既然使用python操作数据库必不可少的得使用pymysql模块 可使用两种方式进行下载安装: 1.使用pip方式下载安装 pip install pymysql 2.IDE方式 安装完成后就可以正常 ...