Go语言入门(十一) 接口编程
时间:2022-07-25
本文章向大家介绍Go语言入门(十一) 接口编程,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
接口
接口的定义
- 接口定义了一个对象化的行为规范
- 只定义规范,不实现
- 具体的对象需要实现规范的细节
- 实践
- type 定义接口 interface
- 接口里面是一组方法签名的集合
type Animal interface {
Talk()
Eat()
Run()
}
- 实现
- 一个对象只要包含接口中的方法,那么就实现了这个接口
- 接口类型的变量可以保存实现该接口的任何类型的实例
type Animal interface {
Talk()
Eat()
Run()
}
type Dog struct {
name string
}
//一个对象只要包含接口中的方法,那么就实现了这个接口
func (d *Dog) Eat() {
fmt.Printf("%s is eatingn",d.name)
}
func (d *Dog) Talk() {
fmt.Printf("%s is talkingn",d.name)
}
func (d *Dog) Run() {
fmt.Printf("%s is runningn",d.name)
}
func main() {
var dog = &Dog{
name: "旺财",
}
var a Animal
//接口类型的变量可以保存实现该接口的任何类型的实例
a = dog
a.Eat()
a.Run()
a.Talk()
fmt.Printf("a:%v,dog:%vn",a,dog)
}
接口实例
- 计算公司所有职员的薪水
- 每个职员的计算方式不同
结构体实现
type Developer struct {
Name string
Base float64
}
func (d *Developer)Calc() float64{
return d.Base
}
type PM struct {
Name string
Base float64
Option float64
}
func (p *PM)Calc() float64{
return p.Base + p.Option
}
type YY struct {
Name string
Base float64
Ratio float64
Option float64
}
func (y *YY)Calc() float64 {
return y.Base + y.Option * y.Ratio
}
type EmployeeMgr struct {
devlist []*Developer
pmlist []*PM
yylist []*YY
}
func (e *EmployeeMgr)Calc() float64 {
var sum float64
for _,v := range e.devlist {
sum += v.Calc()
}
for _,v1 := range e.pmlist {
sum += v1.Calc()
}
for _,v2 := range e.yylist {
sum += v2.Calc()
}
return sum
}
func (e *EmployeeMgr)AddDev(d *Developer) {
e.devlist = append(e.devlist, d)
}
func (e *EmployeeMgr)AddPM(p *PM) {
e.pmlist = append(e.pmlist, p)
}
func (e *EmployeeMgr)AddYY(y *YY) {
e.yylist = append(e.yylist, y)
}
func main() {
var e = &EmployeeMgr{}
dev := &Developer{
Name: "develop",
Base: 5000,
}
e.AddDev(dev)
pm := &PM{
Name: "pm",
Base: 10000,
Option: 2000,
}
e.AddPM(pm)
yy := &YY{
Name: "yy",
Base: 23000,
Option: 9000,
Ratio: 0.67,
}
e.AddYY(yy)
sum := e.Calc()
fmt.Printf("sum:%.2fn",sum)
}
接口实现
type Employee interface {
Calc() float64 //接口返回
}
type Developer struct {
Name string
Base float64
}
func (d *Developer)Calc() float64{
return d.Base
}
type PM struct {
Name string
Base float64
Option float64
}
func (p *PM)Calc() float64{
return p.Base + p.Option
}
type YY struct {
Name string
Base float64
Ratio float64
Option float64
}
func (y *YY)Calc() float64 {
return y.Base + y.Option * y.Ratio
}
type EmployeeMgr struct {
employeelist []Employee
}
func (e *EmployeeMgr) Calc() float64 {
var sum float64
for _,v := range e.employeelist {
sum += v.Calc()
}
return sum
}
func (e *EmployeeMgr) AddEmployee(d Employee) {
e.employeelist = append(e.employeelist,d)
}
func main() {
var e = &EmployeeMgr{}
dev := &Developer{
Name: "develop",
Base: 5000,
}
e.AddEmployee(dev)
pm := &PM{
Name: "pm",
Base: 10000,
Option: 2000,
}
e.AddEmployee(pm)
yy := &YY{
Name: "yy",
Base: 23000,
Option: 9000,
Ratio: 0.67,
}
e.AddEmployee(yy)
sum := e.Calc()
fmt.Printf("sum:%.2fn",sum)
}
空接口
- 空接口没有定义任何方法
- 所以了任何类型都实现了空接口
func main() {
var a interface{}
var b int
a = b
fmt.Printf("a=%v,a:%Tn",a,a)
var c float64
a = c
fmt.Printf("a=%v,a:%Tn",a,a)
}
类型断言
- 需要引入v,ok := i(T)机制
func Describe(a Animal) {
/*代码有坑
dog := a.(*Dog)
dog.Eat()
*/
dog,ok := a.(*Dog)
if !ok {
fmt.Printf("convert to dog errorn")
return
}
fmt.Printf("describe dog succn")
dog.Run()
fmt.Printf("describe dog succ------n")
}
- 类型断言
func DescribeSwitch(a Animal) {
fmt.Printf("DescribeSwitch(a) Beginn")
switch a.(type) {
case *Dog:
dog := a.(*Dog)
dog.Run()
case *Pig:
pig := a.(*Pig)
pig.Eat()
}
fmt.Printf("DescribeSwitch(a) Endn")
}
- 类型断言改进版
func DescribeSwitch(a Animal) {
fmt.Printf("DescribeSwitch(a) Beginn")
switch v:=a.(type) {
case *Dog:
dog := v
dog.Run()
case *Pig:
pig := v
pig.Eat()
}
fmt.Printf("DescribeSwitch(a) Endn")
}
- 指针接收
- 同一个类型可以实现多个接口
type Animal interface {
Talk()
Eat()
Run()
}
type BuRuAnimal interface {
ChiNai()
}
type Dog struct {
name string
}
//一个对象只要包含接口中的方法,那么就实现了这个接口
func (d Dog) Eat() {
fmt.Printf("%s is eatingn",d.name)
}
func (d Dog) Talk() {
fmt.Printf("%s is talkingn",d.name)
}
func (d Dog) Run() {
fmt.Printf("%s is runningn",d.name)
}
func (d Dog) ChiNai() {
fmt.Printf("%s is chinain",d.name)
}
func main() {
var dog = &Dog{
name: "旺财",
}
var a Animal
//接口类型的变量可以保存实现该接口的任何类型的实例
a = dog
//Describe(a)
//DescribeSwitch(a)
a.Eat()
var dogVar = Dog{name:"来福"}
a = dogVar
a.Run()
//实现多个接口
var b BuRuAnimal
b = dog
b.ChiNai()
}
- 接口嵌套
type Animal interface {
Talk()
Eat()
Run()
}
type BuRuAnimal interface {
ChiNai()
}
type AdvanceAnimal interface {
Animal
BuRuAnimal
}
type Dog struct {
name string
}
//一个对象只要包含接口中的方法,那么就实现了这个接口
func (d Dog) Eat() {
fmt.Printf("%s is eatingn",d.name)
}
func (d Dog) Talk() {
fmt.Printf("%s is talkingn",d.name)
}
func (d Dog) Run() {
fmt.Printf("%s is runningn",d.name)
}
func (d Dog) ChiNai() {
fmt.Printf("%s is chinain",d.name)
}
func main() {
var dog = &Dog{
name: "旺财",
}
var a AdvanceAnimal
a = dog
a.ChiNai()
}
接口实例详解
- io包中的writer接口
type Test struct {
data string
}
func (t *Test)Write(p []byte) (n int,err error) {
t.data = string(p)
return len(p),nil
}
func FprintfDemo() {
file,_ := os.Create("./a.txt")
fmt.Fprintf(os.Stdout,"hello worldn")
fmt.Fprintf(file,"hello Worldn") //终端文件写入
var t *Test = &Test{}
//将字符串写入内存,然后再读取
fmt.Fprintf(t,"this is a test interface %s","dasdada")
fmt.Printf("t.data=%sn",t.data)
}
- fmt包中的Stringer接口 返回字符串
type Student struct {
Name string
Age int
}
func (s *Student)String()string {
data,_ := json.Marshal(s)
return string(data)
}
func main() {
var s = &Student{
Name: "ABC",
Age: 22,
}
fmt.Printf("s = %vn",s)
}
- error接口
type MyError struct {
When time.Time
What string
}
func (e *MyError) Error()string{
str:= fmt.Sprintf("time=%v,message=%sn",e.When,e.What)
fmt.Printf("1:%Tn",str)
return str
}
func run()error {
fmt.Printf("0n")
str:=MyError{time.Now(),"it did not work well"}
fmt.Printf("2:%Tn",str)
fmt.Printf("%v,%sn",time.Now(),"error to run!!")
return &str
}
func main() {
if err := run();err!=nil {
fmt.Printf("3:%Tn",err)
fmt.Println(err)
}
}
- 【编程基础】C++初学者需掌握的10个C++特性(中)
- 一步步教你弹性框架-中篇
- 细说ReactiveCocoa的冷信号与热信号系列(2)
- 谈谈个人网站的建立(三)—— 定时任务
- 细说ReactiveCocoa的冷信号与热信号系列(1)
- 【美团技术团队博客】前端组件化开发实践
- Spring中Bean
- 跟Google学写代码--Chromium/base--windows_version源码学习及应用
- 一步步教你弹性框架-下篇
- R语言与机器学习(分类算法)朴素贝叶斯算法
- 【美团技术团队博客】RACSignal的Subscription深入分析
- 谈谈个人网站的建立(八)—— 缓存的使用
- 【编程基础】System.arraycopy()和 Arrays.copyOf()
- 移动端 模拟手机联系人触摸A~Z导航
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- laravel框架与其他框架的详细对比
- ThinkPHP like模糊查询,like多匹配查询,between查询,in查询,一般查询书写办法
- PHP设计模式之数据访问对象模式(DAO)原理与用法实例分析
- PHP实现简单登录界面
- PHP创建XML接口示例
- PHP设计模式之单例模式入门与应用详解
- Laravel框架实现定时Task Scheduling例子
- PHP使用 Pear 进行安装和卸载包的方法详解
- Laravel5.1框架注册中间件的三种场景详解
- 浅谈laravel数据库查询返回的数据形式
- PHP设计模式之策略模式(Strategy)入门与应用案例详解
- 基于Python3读写INI配置文件过程解析
- laravel 解决paginate查询多个字段报错的问题
- php判断/计算闰年的方法小结【三种方法】
- Laravel定时任务的每秒执行代码