目录

  • 接口介绍与定义
  • 空接口和类型断言
  • 指针接收和值接收区别
  • 接口嵌套

接口介绍与定义

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语言学习(十六)接口的更多相关文章

  1. Go语言学习笔记六: 循环语句

    Go语言学习笔记六: 循环语句 今天学了一个格式化代码的命令:gofmt -w chapter6.go for循环 for循环有3种形式: for init; condition; increment ...

  2. 强化学习(十六) 深度确定性策略梯度(DDPG)

    在强化学习(十五) A3C中,我们讨论了使用多线程的方法来解决Actor-Critic难收敛的问题,今天我们不使用多线程,而是使用和DDQN类似的方法:即经验回放和双网络的方法来改进Actor-Cri ...

  3. 【原创】go语言学习(六)函数详解2

    目录 变量作用域和可见性 匿名函数 闭包 课后练习 变量作用域和可见性 1.全局变量量,在程序整个生命周期有效. var a int = 10 2.局部变量量,分为两种: 1)函数内定义, 2)语句句 ...

  4. Dart语言学习(十二) Dart面向对象

    Dart作为一种高级语言,支持面向对象的很多特性,并且支持基于mixin的继承方式. 基于mixin的继承方式是指:一个类可以继承自多个父类,相当于其他语言里的多继承. 所有的类都有同一个基类Obje ...

  5. Dart语言学习(十) Dart流程控制语句

    一.条件语句:if.if...elseif.if...elseif...else int score = 95; if (score >=90) { print('优秀'); } else if ...

  6. C 语言学习 第六次作业总结

    本次作业,同学们开始学习函数.通过之前和同学们的沟通,似乎同学们在这里遇到的问题比较多.下面,我先帮同学们整理下函数的相关知识点. 什么是函数 首先,需要明确的是,什么是函数.所谓函数,也就是一段有名 ...

  7. C语言学习第六章

    今天开始尝试改变! 今天要学习函数,一个C语言中的重要组成部分. 首先先聊聊为什么要使用函数?随着学习的深入很多人会发现某段的代码重复使用的几率很大,而如果用一次写一次的话很明显的效率就会比较低,如果 ...

  8. Go语言学习之7 接口实例、终端文件读写、异常处理

    本节主要内容: 1. 终端读写2. 文件读写3. 命令行参数4. Json5. 自定义错误 1. 终端读写 操作终端相关文件句柄常量    os.Stdin:标准输入    os.Stdout:标准输 ...

  9. GO语言学习(六)Go 语言数据类型

    在 Go 编程语言中,数据类型用于声明函数和变量. 数据类型的出现是为了把数据分成所需内存大小不同的数据,编程的时候需要用大数据的时候才需要申请大内存,就可以充分利用内存. Go 语言按类别有以下几种 ...

  10. Go语言学习笔记(9)——接口类型

    接口 Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口. /* 定义接口 */ type interface_name in ...

随机推荐

  1. 在论坛中出现的比较难的sql问题:22(触发器专题3)

    原文:在论坛中出现的比较难的sql问题:22(触发器专题3) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. 所以,觉得有必要记录下 ...

  2. VS.NET(C#)--2.2_事件

    事件 事件 由用戶行为生成系统触发(事件处理程序).在ASP.NET中,对象可以触发事件.用户在浏览器对服务器控件的任何行为都可能触发事件,但是在服务器端处理. 页面和控件事件 它们继承自contro ...

  3. python——操作系统的发展史

    一.手工操作 —— 穿孔卡片 1946年第一台计算机诞生--20世纪50年代中期,计算机工作还在采用手工操作方式.此时还没有操作系统的概念.    程序员将对应于程序和数据的已穿孔的纸带(或卡片)装入 ...

  4. Java源码阅读之ArrayList

    基于jdk1.8的ArrayList源码分析. 实现List接口最常见的大概就四种,ArrayList, LinkedList, Vector, Stack实现,今天就着重看一下ArrayList的源 ...

  5. centos7.x安装docker-ce

    环境: 系统:centos7.x docker版本:19.03.2 安装方式:yum 参考官方安装文档:https://docs.docker.com/install/linux/docker-ce/ ...

  6. tree 树形加载及增删改

    //异步1<template> <div class="addequipment org"> <div class="top"&g ...

  7. cell上的按钮点击和左滑冲突

    cell上的某个按钮的点击事件,当cell左滑的时候,只要活动的区域也在按钮上,那么按钮的点击事件也会调用. fix: 给按钮添加一个手势(TapGesture)那么当点击的时候就会响应点击手势的方法 ...

  8. 基于SpringBoot的多模块项目引入其他模块时@Autowired无法注入其他模块stereotype注解类对象的问题解决

    类似问题: 关于spring boot自动注入出现Consider defining a bean of type 'xxx' in your configuration问题解决方案 排查原因总结如下 ...

  9. 七年开发经验详解JVM的GC 算法

    概述 GC 是 JVM 自带的功能,它能够自动回收对象,清理内存,这是 Java 语言的一大优势,但是GC绝不仅伴随着Java,相反,GC历史比Java更悠久.关于GC,我认为有四个问题需要解决: 为 ...

  10. extjs6 创建工程和打包发布

    准备工作: 下载extjs6的开发包,我这里是试验版:ext-6.6.0-trial.zip.解压到某个目录,我这里解压到:D:\tools\about-ext\ext-6.6.0-trial 目录下 ...