zoukankan      html  css  js  c++  java
  • Golang 接口(interface)

    前言:

    接口是1种以type关键字声明的数据类型

    如果想满足这种类型  就必须实现接口中规定的所有方法,从而起到了约束、限定行为的目的。

    有了接口的约束 那些自定义struct就更具有规范性,不同的struct遵循了同1套规范并且去遵循这1套规范。

    秦始皇一统6个不同国家之后  统一了度量衡、人同文、车同轨。

    既方便了现有这些人(原本来自不同国界的人彼此之间相互沟通(调用),也为以后继续开疆扩土打下基础。

    package main
    
    import "fmt"
    
    //usb interface规定都要实现 usb接口中的start和end方法都可以称为usb interface类型
    type usb interface {
    	statr()
    	end()
    }
    
    //相机 struct
    type camera struct{ brand string }
    
    //相机实现usb interface的start方法
    func (c camera) statr() {
    	fmt.Printf("%s相机插入电脑的USB接口
    ", c.brand)
    }
    
    //相机实现usb interface的end方法
    func (c camera) end() {
    	fmt.Printf("%s相机插入电脑的USB接口 
    ", c.brand)
    }
    
    //手机 struct
    type phone struct{ brand string }
    
    //手机实现usb interface的start方法
    func (p phone) statr() {
    	fmt.Printf("%s手机插入电脑的USB接口
    ", p.brand)
    }
    
    //手机实现usb interface的end方法
    func (p phone) end() {
    	fmt.Printf("%s手机拔出电脑的USB接口
    ", p.brand)
    }
    
    //电脑 struct
    type computer struct{ brand string }
    
    //电脑的usbWork这里体现多态的重点!仅接受usb类型的参数(实现start和end方法就属于usb 接口类型) who cares what kind of ekectronics it is?
    func (c computer) usbWork(e usb) {
    	e.statr()
    	e.end()
    
    }
    
    func main() {
    	lenov := computer{brand: "lenov"}
    	Jphone := phone{brand: "Jphone"}
    	Soni := camera{brand: "soni"}
    	lenov.usbWork(Jphone)
    	lenov.usbWork(Soni)
    
    }
    

      

    Golang为什么需要 interface 类型

    之前使用Python、JavaScript..动态类型的语言较多,对面向对象中多态特的特性感受不是很深刻。

    由于Golang是强类型的语言,变量一经声明不存在数据类型自动识别/修改。所以它需要接口规范

    现在我有1个struct human和另1个struct cats它们都有自己共有的属性-feet、方法-move。

    如何使这2个struct都可以作为同1种类型的函数参数,传入到1个run函数中,并执行它们共有的方法move(),输出2种动物2种不同的走路方式

    //1.Go中引出接口概念
    
    package main
    
    import "fmt"
    
    /*
    定义1个animal接口:只要有类型接口中的规范有move方法,
    就可以称之为这种animal interface类型
    */
    type animal interface {
    	move()
    }
    
    //hunma 结构体
    type human struct {
    	name  string
    	feet uint8
    }
    
    //人类实现了 move方法,就属于animal interface类型
    func (h human) move() {
    	fmt.Printf("%s 使用 %d条腿走路~
    ", h.name, h.feets)
    }
    
    //dogs 猫科动物结构体
    type cats struct {
    	name  string
    	feet uint8
    }
    
    //猫科动物实现了move方法,也属于animal interface类型
    func (d cats) move() {
    	fmt.Printf("%s 使用 %d条腿走路~
    ", d.name, d.feets)
    }
    
    /*
    run函数接收值为aniaml接口类型的参数
    现在human和animal的类型一致(都实现了move方法!)
    所有都可以作为参数传到run函数里面
    */
    func run(a animal) {
    	a.move()
    
    }
    
    func main() {
    	p1 := human{name: "光头强", feet: 2}
    
    	var d1 cats
    	d1.name = "熊二"
    	d1.feet = 4
    
    	run(p1)
    	run(d1)
    
    }
    

      

    对不同类型进行接口约束

    package main
    
    import (
    	"fmt"
    )
    
    //自行车
    type bicycle struct {
    	brand string
    }
    
    //自行车实现得能开
    func (b bicycle) drive() {
    	fmt.Printf("I've got a/an %s
    .", b.brand)
    }
    
    //四轮汽车也得能开
    type car struct {
    	brand string
    }
    
    func (c car) drive() {
    	fmt.Printf("I've got a/an %s.
    ", c.brand)
    }
    
    //飞机也得能开
    type airplane struct {
    	brand string
    }
    
    func (a airplane) drive() {
    	fmt.Printf("I've got a/an %s.
    ", a.brand)
    }
    
    //定义1个transport 接口类型
    type transport interface {
    	drive()
    }
    
    //想要批量生产transport,就得有自己的标准
    func factory(t transport) {
    	t.drive()
    }
    
    func main() {
    	var feige = bicycle{
    		brand: "飞鸽",
    	}
    	var bens = car{
    		brand: "大奔",
    	}
    	var boyin747 = airplane{
    		brand: "波也",
    	}
    
    	factory(feige)
    	factory(bens)
    	factory(boyin747)
    
    }
    

      

    接口的定义与实现

    定义

    interface类型可以定义1组方法,但是不需要在接口内部实现这些方法。并且interface内部不能包含任何变量

    哪个自定义类型 (如struct)想要使用哪个接口时,需要把哪个接口中定义的方法全部实现。

    type 接口名称 interface {
    	方法名1(参数1,参数2)(返回值1,返回值2)
            方法名2(参数1,参数2)(返回值1,返回值2)
        
    }
    

      

    实现

    Golang中的接口实现起来灵活、低耦合,因为不需要像Java中1个类 class A implement interface b 通过implement关键字来显式实现。

    只要 变量A中含有 接口B中定义的所有方法 ,变量A就可以称为interfaceB类型。

    接口的使用

    接口的使用就是你遵循了该接口中规定的全部标准(实现了接口中定义的方法)之后,你就可以作为该接口类型的变量、参数在Go中畅行无阻的使用。

    使用值接收者实现接口和使用值接收者实现接口的区别?
    使用值接收者实现接口的方法:接口既可以存结构体类型 也能存结构体类型指针的变量
    使用指针接收者实现接口的方法:接口只能存储 指针类型的结构体的变量
    package main
    
    import "fmt"
    
    //usb interface规定
    type usb interface {
    	statr()
    	end()
    }
    
    //相机 struct
    type camera struct{ brand string }
    
    //相机使用指针接收者 实现usb interface的start方法
    func (c *camera) statr() {
    	fmt.Printf("%s相机插入电脑的USB接口
    ", c.brand)
    }
    
    //相机使用指针接收者 实现usb interface的end方法
    func (c *camera) end() {
    	fmt.Printf("%s相机插入电脑的USB接口 
    ", c.brand)
    }
    
    //手机 struct
    type phone struct{ brand string }
    
    //手机实现usb
    func (p phone) statr() {
    	fmt.Printf("%s手机插入电脑的USB接口
    ", p.brand)
    }
    
    //手机实现usb interface的end方法
    func (p phone) end() {
    	fmt.Printf("%s手机拔出电脑的USB接口
    ", p.brand)
    }
    
    //电脑 struct
    type computer struct{ brand string }
    
    
    func (c computer) usbWork(e usb) {
    	e.statr()
    	e.end()
    
    }
    
    func main() {
    	/*
    	使用值接收者实现接口和使用值接收者实现接口的区别?:
    	使用值接收者实现接口的方法:既可以存结构体类型 也能存结构体类型指针的变量
    	使用指针接收者实现接口的方法:接口只能存储 指针类型的结构体的变量
    	*/
    	var u usb
    	//使用值接收者实现接口的方法:既可以存结构体类型的变量、也可以存结构体指针类型的变量
    	phone1:=phone{brand:"8848手机"}
    	phone2:=phone{brand:"乐视手机"}
    	u=phone1
    	fmt.Printf("%T
    ",u)
    	u=&phone2
    	fmt.Printf("%T
    ",u)
    
    	//使用指针接收者实现接口的方法:接口只能存储 指针类型的变量 
    	camera1:=&camera{brand:"苏尼"}
    	u=camera1
    	fmt.Printf("%T
    ",u)
    
    }
    

      

    空接口

    空接口interface{ } 就是我没有定义任何方法(规范),任意类型不需要实现任何方法(规范) 就可以作为空接口类型作为变量和参数使用

    为什么 fmt.Print( )函数可以接收任何数据类型呢?

    func Println(a ...interface{}) (n int, err error) {
    	return Fprintln(os.Stdout, a...)
    }

    //interface{}就是空接口

    空接口是指没有定义任何方法的接口。因此任何变量和参数都属于空接口类型。

    空接口类型的变量可以存储任意类型的变量。包揽Golang中任何数据类型。

    package main
    
    import "fmt"
    
    type everything interface{}
    
    func main(){
    	var m1  map[string]everything
    	m1=make(map[string]everything,18)
    	m1["name"]="阿水"
    	m1["married"]=true
    	m1["age"]=19
    	m1["hobby"]=[]string{"抽烟","喝酒","烫头"}
    	fmt.Println(m1)
    	//哈哈.....终于实现Python里面的字典了吧!
    	
    }
    

    空接口数据类型断言

    如果任何变量和参数都属于空接口类型,那如何在Go中识别参数和变量具体的数据类型呢?这就需要类型断言。

    arg.(string) 方式1
    arg.(type)   方式2

      

    如果你要使用Golang 重构Cpython,通过空接口我们我们可以把任意数据类型的变量传入1个Python函数中

    那么怎么在函数里面判断变量到底数据属于哪个类型呢?

    package main
    
    import "fmt"
    
    //类型断言
    func assert(arg interface{}){
    	value,ok:=arg.(string)
    	if ok{
    		fmt.Printf("这是字符型值为%s
    ",value)
    	}
    
    } 
    //类型断言2
    func evaluate(arg interface{}) {
    	switch v := arg.(type) {
    	case string:
    		fmt.Printf("%v is a string type
    ", v)
    	case int:
    		fmt.Printf("%v is a int type
    ", v)	
    	case bool:
    		fmt.Printf("%v is a bool type
    ", v)			
    
    	}
    }
    
    func main(){
    	a:="11111"
    	assert(a)
    	evaluate(100)
    }
    

      

    参考

  • 相关阅读:
    [一起面试AI]NO.9 如何判断函数凸或非凸
    [一起面试AI]NO.8 在机器学习中,常用的损失函数有哪些?
    [一起面试AI]NO.5过拟合、欠拟合与正则化是什么?
    [一起面试AI]NO.4特征工程主要包括什么?
    [一起面试AI]NO.3分类问题常用的性能度量指标有哪些
    MySQL中自增ID修改起始值
    折半查找算法(Python版)
    彻底解决安卓7.0及以上版本抓包https失败
    Charles抓包2-Charles抓取https请求
    Charles抓包1-Charles安装汉化(附正版注册码)
  • 原文地址:https://www.cnblogs.com/sss4/p/12689357.html
Copyright © 2011-2022 走看看