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)
    }
    

      

    参考

  • 相关阅读:
    js正则表达式中的问号使用技巧总结
    380. Insert Delete GetRandom O(1)
    34. Find First and Last Position of Element in Sorted Array
    162. Find Peak Element
    220. Contains Duplicate III
    269. Alien Dictionary
    18. 4Sum
    15. 3Sum
    224. Basic Calculator
    227. Basic Calculator II
  • 原文地址:https://www.cnblogs.com/sss4/p/12689357.html
Copyright © 2011-2022 走看看