Go入门(四)接口



什么是接口,只要记住一句,接口是一种类型。
接口应用的场景:我不关心接口的类型,我只关心能调用他的方法。

如果一个变量,他实现了接口里的所有方法,那么他就是实现了这个接口


1.需求

现在有 狗 和 猫 两个结构体,都能叫,如果被 这个函数调用了,他们都能叫,如果在函数往里传参的时候,指定是穿进去的什么参数。

package main

import "fmt"

type dog struct{}
type cat struct{}

func (d dog) speak() {
	fmt.Println("汪汪叫")
}

func (c cat) speak() {
	fmt.Println("喵喵叫")
}

func da(x) {
	x.speak() // 这个应该是个什么类型?
}

func main() {
	var dog1 dog
	var cat1 cat
	da(dog1)
}

2.使用接口解决这个问题

package main

import "fmt"

type dog struct{}
type cat struct{}

// 声明接口
type speaker interface {
	speak() // speak 方法
}

func (d dog) speak() {
	fmt.Println("汪汪叫")
}

func (c cat) speak() {
	fmt.Println("喵喵叫")
}

func da(x speaker) {
	x.speak() // 传进来一个x,无论这个x是什么样式,都打出来
}

func main() {
	var dog1 dog
	var cat1 cat
	da(dog1)
	da(cat1)
}


3.接口的定义

type 接口的名字 interface{

	方法名1:(参数1,参数2,参数3)(返回值1,返回值2)
	
	方法名1:(参数1,参数2,参数3)(返回值1,返回值2)
	
}

4.猫狗的另一个例子

package main

import "fmt"

type animal interface {
	move()      // 移动
	eat(string) // 吃东西
}

type dog struct { // 先声明 猫和 狗两个实例
	name string
	feet int
}
type cat struct {
	name string
	feet int // 几条腿
}

func (c cat) eat(foot string) {
	fmt.Println("猫吃啥?", foot) // 猫吃啥?猫吃鱼
}
func (c cat) move() {
	fmt.Println("猫跑了")
}

func (d dog) eat(foot string) {
	fmt.Println("狗吃啥?", foot) //狗吃东西
}
func (d dog) move() {
	fmt.Println("狗跑了")
}

func main() {
	var anmin animal // 声明接口
	dog1 := dog{
		name: "小黑狗",
		feet: 4,
	}

	anmin = dog1
	anmin.move()
	anmin.eat("骨头")

	cat1 := cat{
		name: "小黄猫",
		feet: 8,
	}

	anmin = cat1
	anmin.eat("鱼")
	anmin.move()
}


// 输出
狗跑了
狗吃啥? 骨头
猫吃啥? 鱼  
猫跑了 


5.值接受者和指针接受者的区别

当接受者为值类型的时候,你可以往里传指针,但是当接受者是指针类型的时候,你不能往里传值。

package main

import "fmt"

type animal interface {
	move()      // 移动
	eat(string) // 吃东西
}

type dog struct { // 先声明 猫和 狗两个实例
	name string
	feet int
}

func (d dog) eat(foot string) {
	fmt.Println("狗吃啥?", foot) //狗吃东西
}
func (d dog) move() {
	fmt.Println("狗跑了")
}

func main() {
	var anmin animal // 声明接口
	dog1 := dog{
		name: "小黑狗",
		feet: 4,
	}

	anmin = dog1
	anmin.move()
	anmin.eat("骨头")

	fmt.Println("****************")
	anmin = &dog1
	anmin.move()
	anmin.eat("骨头")
}

// 输出
狗跑了
狗吃啥? 骨头
****************
狗跑了
狗吃啥? 骨头



6.结构体的嵌套

上边写的都是多个类型实现同一个接口,实际上也可以一个类型实现多个接口。

type eater interface {
	eat(string) // 吃东西
}

type mover interface {
	move() // 实现了move这个接口
}

type dog struct { // 先声明 猫和 狗两个实例
	name string
	feet int
}

func (d dog) eat(foot string) {
	fmt.Println("狗吃啥?", foot) //狗吃东西
}
func (d dog) move() {
	fmt.Println("狗跑了")
}

dog对应这 movereater 这两个接口,而且还可以实现接口的嵌套。




7.空接口

type 接口名字 interface {} // 里面任何东西都不写

空接口没有必要命名,通常定义为如下形式

interface{}  // 空接口


空接口,也就是说所有的类型都实现了这个接口

这样传什么值都可以了。

空接口可以存储任意类型的值

package main

import "fmt"

func main() {
	var m1 = make(map[string]interface{}) // 声明m1
	m1["name"] = "赵"
	m1["age"] = 20
	m1["hopy"] = []string{"吃饭", "睡觉"}
	fmt.Println(m1)
}

// 输出
map[age:20 hopy:[吃饭 睡觉] name:]
package main

import "fmt"

// 空接口作为参数
func f1(x interface{}) {
	fmt.Println(x)
	fmt.Printf("%T,%v",x,x)
}

func main() {
	var m1 = make(map[string]interface{}) // 声明m1
	m1["name"] = "赵"
	m1["age"] = 20
	m1["hopy"] = []string{"吃饭", "睡觉"}
	fmt.Println(m1)

	f1("你好")
	f1(15)
	f1(true)
}


// 输出
string,你好15
int,15true
bool,true

8. 把空接口的值取出来

如何取出来呢?就是考猜

package main

import "fmt"

func f1(x interface{}) {
	v, ok := x.(string) // 猜他是什么类型
	if !ok {
		fmt.Println("猜错了")
	} else {
		fmt.Println(v)
	}
}

func main() {
	f1(2)
}

// 输出
猜错了
posted @ 2021-04-09 02:23  沧海一声笑rush  阅读(57)  评论(0编辑  收藏  举报