Go接口

接口是啥

在面向对象的领域里,接口一般这样定义:接口定义一个对象的行为。接口只指定了对象应该做什么,至于如何实现这个行为(即实现细节),则由对象本身去确定。

在 Go 语言中,接口就是方法签名(Method Signature)的集合。当一个类型定义了接口中的所有方法,我们称它实现了该接口。这与面向对象编程(OOP)的说法很类似。接口指定了一个类型应该具有的方法,并由该类型决定如何实现这些方法

接口:面向对象的领域里,接口一般这样定义;接口定义一个对象的行为

鸭子类型

简单来说

鸭子类型 有个鸭子。speak方法,有run方法,子类只要实现了两个方法,我就认为是鸭子,从下往上的(go也是鸭子类型

接口的定义和使用

接口是一系列方法的集合(规范行为),结构体是一系列属性的集合

package main

import "fmt"

// go也是鸭子类型
// 接口:面向对象的领域里,接口一般这样定义;接口定义一个对象的行为
// 实际开发中接口还是很重要的,
// 鸭子类型 有个鸭子。speak方法,有run方法,子类只要实现了两个方法,我就认为是鸭子,从下往上的
// 接口是一系列方法的集合(规范行为),结构体是一系列属性的集合

//  定义接口(定义一个鸭子接口,speak,run方法)

type Duck interface {
   // 方法名 参数  返回值
   speak(word string) //speak方法
   run() string       //run方法
}

// 定义普通鸭子结构体
type PDuck struct {
   Id   int
   Name string
}

// 定义一个唐老鸭结构体
type TDuck struct {
   Id    int
   Name  string
   Color string
}

// 目前为止他们没有任何关系,但是想让两个鸭子都实现duck接口
// 结构体实现一个接口,只要绑定接口中的所有方法,就叫实现该接口

func (p PDuck) speak(word string) {
   fmt.Println("普通鸭子正在叫!",word)

}
func (p PDuck) run() string {
   return "普通鸭子 正在跑!"
}

func (t TDuck) speak(word string){
   fmt.Println("唐老鸭正在叫!")
}

func (t TDuck) run() string {
   return "唐老鸭 正在跑!"
}

func main() {
   // 1得到一个普通鸭子对象
   pduck := PDuck{1,"肉鸭"}
   // 得到一个唐老鸭对象
   tduck := TDuck{1,"唐老鸭","white"}

   pduck.speak("嘎嘎嘎")
   res := tduck.run()
   fmt.Println(res)
   // 侵入式接口()接口没了,子类报错
   // 非侵入式接口(接口没了,不影响代码)  装饰器就是非侵入式接口

}
--------------------------------------------------
普通鸭子正在叫! 嘎嘎嘎
唐老鸭 正在跑!

Go属于非侵入式接口

接口的内部使用

把接口类型转成struct,属性,自有方法也有了

类型断言

package main

import "fmt"

//  接口内部表示

// 我们可以把接口看做内部的一个元祖(type value)
// type 是接口底层的具体类型(concrete type),而value 是具体类型的值

type Dog interface {
	run()
	eat(food string)
}

type Wolf struct {
	name string
	kind string
}

type GaoF struct {
	name  string
	kind  string
	color string
}

func (Gf GaoF) run() {
	fmt.Println("普通的狗正在跑!")

}
func (Gf GaoF) eat(food string) {
	fmt.Println("普通的狗正在吃:", food)
}

func (wolf Wolf) run() {
	fmt.Println("狼正在奔跑!")

}

func (wolf Wolf) eat(food string) {
	fmt.Println("狼正在吃:", food)
}

// 4 把接口类型转成struct,属性,自有方法也有了
func main() {
	// 类型断言
	var wolf Dog= Wolf{"哈士奇", "大傻子"}
	// 断言是Wolf类型,如果成功,ok是True,v就是结构体对象
	v1, ok1:= wolf.(Wolf)
	fmt.Println(v1)
	fmt.Println(ok1)
	fmt.Println(v1.name)

	// 断言是GaoF类型,断言失败ok是false v是类型的空值,因为没有赋值
	v2,ok2 := wolf.(GaoF)
	fmt.Println(v2)
	fmt.Println(ok2)

}

image-20210228164111675

但是这种并不是常用的方式

常用方式(类型选择器)

通过switch来实现

package main

import "fmt"

//  接口内部表示

// 我们可以把接口看做内部的一个元祖(type value)
// type 是接口底层的具体类型(concrete type),而value 是具体类型的值

type Dog interface {
   run()
   eat(food string)
}

type Wolf struct {
   name string
   kind string
}

type GaoF struct {
   name  string
   kind  string
   color string
}

func (Gf GaoF) run() {
   fmt.Println("普通的狗正在跑!")

}
func (Gf GaoF) eat(food string) {
   fmt.Println("普通的狗正在吃:", food)
}

func (wolf Wolf) run() {
   fmt.Println("狼正在奔跑!")

}

func (wolf Wolf) eat(food string) {
   fmt.Println("狼正在吃:", food)
}

func test(dog Dog) {
   if v, ok := dog.(GaoF); ok {
      fmt.Println("我是高夫!")
      fmt.Println(v)
   } else if v, ok := dog.(Wolf); ok {
      fmt.Println("我是狼!")
      fmt.Println(v)
   }
}

// 试用switch 选择成功,拿到结构体对象
func test2(dog Dog) {
   switch v:=dog.(type) {
   case GaoF:
      // v在哪个下面这个V就是谁
      fmt.Println(v.color)
      fmt.Println("我是高夫!")
   case Wolf:
      fmt.Println(v.name)
      fmt.Println("我是狼!")
   default:
      fmt.Println("我是鸭子类型!")
   }

}

// 4 把接口类型转成struct,属性,自有方法也有了
func main() {
	// 类型断言
	var wolf Dog = Wolf{"哈士奇", "大傻子"}
	var gf Dog = GaoF{"高夫", "迪士尼IP", "black"}
	test(gf)
	test(wolf)
	test2(gf)
	test2(wolf)

}

image-20210228172636792

也就是说我现在可以把一个结构体类型转换成接口类型

空接口

任何方法都没有,所有数据类型都实现了空接口

package main

import "fmt"

// 定义空接口
type Cat interface {
}

func test3(c Cat)  {
   switch v:=c.(type) {
   case int:
      fmt.Println(v)
      fmt.Println("我是int类型!")
   case string:
      fmt.Println(v)
      fmt.Println("我是string类型!")
   case Cat:
      fmt.Println("空类型")
   }
}

func main() {
   var a int = 1
   var b string = "猫猫"
   var c [3]int
   var d Cat //空接口类型

   d = a
   d = b
   d = c
   fmt.Println(d)
   test3(a)

}

// 小提示泛型
// 所谓的泛型就是等你来了之后再去确定你是什么类型

image-20210228233047978

匿名空接口

package main

import "fmt"

func test4(b interface{}) {
	switch v := b.(type) {
	case int:
		fmt.Println(v)
		fmt.Println("int类型!")
	case [4]int: // 不能使用[...]int 判断
		fmt.Println(v)
		fmt.Println("数组类型")
	}
}

func main() {
	a :=[...]int{1, 23, 4, 5}
	test4(a)
	}

接口的嵌套

package main

import "fmt"

type Cow interface {
   Animal // 类似于父类
   Drink()
}
// 如果结构体实现cow接口(实现Drink,和animal肿了eat sleep)

type Animal interface {
   eat()
   sleep()
}

type RedCow struct {
   name  string
   color string
}

type WaterCow struct {
   name  string
   color string
   hobby string
}

func (rc RedCow) Drink() {
   fmt.Println("红牛正在喝水!")
}

func (wc WaterCow) Drink() {
   fmt.Println("水牛正在喝水!")
}

// redcow实现animal接口
func (rc RedCow) eat() {
   fmt.Println("红牛正在吃!")
}

func (rc RedCow) sleep() {
   fmt.Println("红牛正在睡觉!")
}

// 这样红牛即实现了cow也实现了animal接口

func main() {
   var redcow = RedCow{"红牛", "红色"}
   var a Animal
   var b Cow
   // 一旦转到某个接口上,只能使用接口的方法,自身属性和方法需要类型断言后才能使用
   fmt.Println(a)
   fmt.Println(b)
   a = redcow
   b = redcow
   fmt.Println(a)
   fmt.Println(b)
}

image-20210302133117886

自定义集合类型

在python中集合类型不能有重复元素,可以添加修改

Make和New的区别

package main

import "fmt"

// make和new的区别
// new返回的是指向type的指针,make直接返回的是type的类型值

type Rabbit struct {
	name  string
	sex   int
	hobby string
}

func main() {
	//make是引用类型初始化的时候使用的
	var a map[int]string = make(map[int]string)
	fmt.Println(a)

	var rb1 = new(Rabbit)
	fmt.Println(rb1)
	var rb2 = &Rabbit{}
	fmt.Println(rb2)

	var rb3 = make([]int, 3, 4)
	fmt.Println(rb3)
	var rb4 *[]int = new([]int) //他不是切片类型而是指向切片类型的指针
	fmt.Println(rb4)
	(*rb4) = append((*rb4), 33, 44, 55, 66)
	fmt.Println(*rb4)
}

image-20210302152402239

结构体取代类

一个包算是一个类,用的话导入使用

package Tiger

type Tiger struct {
   Name    string
   Address string
   Hobby   string
}

func New(name string, address string, hobby string) Tiger {
   return Tiger{name, address, hobby}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值