【原创】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 ...
随机推荐
- 【Linux】Shell批量修改文件名
修改文件名,替换中间字符: 例如:ABC_define_EFG.jpg,要把中间的define替换成argument: 用如下脚本即可: for var in *; do mv "$var& ...
- [Luogu5280][ZJOI2019]线段树(线段树+DP)
https://www.luogu.org/blog/Sooke/solution-p5280 首先想到对线段树上每个点分别维护有多少棵线段树在它上有标记(f[]),然后想到对于每个操作,根据转移的不 ...
- hdu 2132... 被基本问题考住了。。
Problem Description We once did a lot of recursional problem . I think some of them is easy for you ...
- Python遗传和进化算法框架(一)Geatpy快速入门
https://blog.csdn.net/qq_33353186/article/details/82014986 Geatpy是一个高性能的Python遗传算法库以及开放式进化算法框架,由华南理工 ...
- linux Ubuntu14.04 make编译文件报错:No rule to make target `/usr/lib/libpython2.7.so', needed by `python/_pywraps2.so'. Stop.
错误过程:当“make”编译文件时报错No rule to make target `/usr/lib/libpython2.7.so', needed by `python/_pywraps2.so ...
- 同步IO,异步IO,阻塞,非阻塞的定义与区别
异步I/O 是指用户程序发起IO请求后,不等待数据,同时操作系统内核负责I/O操作把数据从内核拷贝到用户程序的缓冲区后通知应用程序.数据拷贝是由操作系统内核完成,用户程序从一开始就没有等待数据,发起请 ...
- 命令“regsvr32 /s /n /i:user "XXXXXX"”已退出,代码为 3
问题:命令“regsvr32 /s /n /i:user "F:\XXXXXXXXXXXXXXXXX\Release\One.ocx"”已退出,代码为 3 解决方法: The is ...
- 记一次bypass某场景GD库及拓展分析
0x00 前言 gou楼兰师傅发来个站说是过不了gd库,问我有啥办法没有,给了他之前海贼师傅说的jpg_payload脚本,但是绕不过,问他拿了站点,写了个jpg_payload批量的fuzz脚本,f ...
- 华为SDN:解决传统网络3大问题
转:http://mp.ofweek.com/tele/a145613326756 科技潮人 2013-08-05 14:20 传统网络之困 互联网爆炸式增长,除了规模和发展速度远超之前所有曾出现的数 ...
- RHEL/CentOS/Fedora各种源(EPEL、Remi、RPMForge、RPMFusion)
参考:RHEL/CentOS/Fedora各种源(EPEL.Remi.RPMForge.RPMFusion)配置 简介 CentOS 默认自带 CentOS-Base.repo 源, 但官方源中去除了 ...