【原创】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 ...
随机推荐
- MAMP PRO 在osx 10.10 错误处理
新更新的osx10.10之后,启动MAMP会发现Apache无法启动, 处理如下: 1.cd /Applications/MAMP/Library/bin 2.mv envvars _envvars ...
- Redis缓存如何保证一致性
为什么使用Redis做缓存 MySQL缺点 单机连接数目有限 对数据进行写速度慢 Redis优点 内存操作数据速度快 IO复用,速度快 单线程模型,避免线程切换带来的开销,速度快 一致性问题 读数据的 ...
- iOS - 反射机制: objc_property_t的使用
iOS属性反射:说白了,就是将两个对象的所有属性,用动态的方式取出来,并根据属性名,自动绑值.(注意:对象的类,如果是派生类,就得靠其他方式来实现了,因为得到不该基类的属性.) 常用的反射方式,有如下 ...
- Linux查找文件之Find命令
Linux系统文件中常用属性包括以下内容:名称,大小,权限,属主,属组,修改时间,访问时间等.在庞大的Linux系统中查询文件,需要借助查找工具来实现,依此可以查询相同或指定属性的文件,本文所讲的查询 ...
- 如何使用.gitignore文件删除掉已经提交的文件
如何使用.gitignore文件删除掉已经提交的文件 2018.06.06 22:13:38字数 96阅读 116 如果你的文件已经提交,而此时你才发现忘了添加.gitignore文件,不用担心, ...
- c# 虚属性
- Paper Reading:Deep Neural Networks for YouTube Recommendations
论文:Deep Neural Networks for YouTube Recommendations 发表时间:2016 发表作者:(Google)Paul Covington, Jay Adams ...
- LRU(最近最少使用)(python实现)
""" python3 only LRU cache """ from collections import OrderedDict fro ...
- js基础知识1
本博客转自某不知名程序员 1. JavaScript基础分为三个部分: ECMAScript:JavaScript的语法标准.包括变量.表达式.运算符.函数.if语句.for语句等. DOM:操作网页 ...
- linux fstab下挂载错误导致cannot open access to console, the root account is locked的问题
用 deepin 安装 u 盘启动,出现选择安装语言的界面时,按 ctrl+alt+T,进入 tty,然后输入 startx,进入 live cd 模式,挂载硬盘的根分区,然后修改 /etc/fsta ...