值接收者和指针接收者

使用值接收者实现接口与使用指针接收者实现接口的区别?

使用值接收者实现接口:结构体类型和结构体指针类型的变量都能存

使用指针接收者实现接口:只能存结构体指针类型的变量

package main

import "fmt"

// 使用值接收者和指针接收者的区别

type animal interface {
	move()
	eat(string)
}

type cat struct {
	name string
	feet int8
}

// // 使用值接收者实现了接口的所有方法
// func (c cat) move() {
// 	fmt.Println("走猫步...")
// }

// func (c cat) eat(food string) {
// 	fmt.Printf("猫吃%s...\n", food)
// }

// 使用指针接收者实现了接口的所有方法
func (c *cat) move() {
	fmt.Println("走猫步...")
}

func (c *cat) eat(food string) {
	fmt.Printf("猫吃%s...\n", food)
}

func main() {
	var a1 animal

	c1 := cat{"tom", 4}  // cat
	c2 := &cat{"假老练", 4} // *cat

	// a1 = c1
	a1 = &c1        // 实现animal这个接口的是cat的指针类型
	fmt.Println(a1) // {tom 4} &{tom 4}
	a1 = c2
	fmt.Println(a1) // &{假老练 4}
}

接口和类型的关系

多个类型可以实现同一个接口

一个类型可以实现多个接口

package main

import "fmt"

// 同一个结构体可以实现多个接口
// 接口还可以嵌套

type animal interface {
	mover
	eater
}

type mover interface {
	move()
}

type eater interface {
	eat(string)
}

type cat struct {
	name string
	feet int8
}

// cat实现了moveer接口
func (c *cat) move() {
	fmt.Println("走猫步...")
}

// cat实现了eater接口
func (c *cat) eat(food string) {
	fmt.Printf("猫吃%s...\n", food)
}

func main() {

}

空接口

没有必要起名字,通常定义成下面的格式:

interface {} // 空接口

所有的类型都实现了空接口,也就是任意类型的变量都能保存到空接口中

package main

import "fmt"

// 空接口

// interface: 关键字
// interface(): 空接口类型

// 空接口作为函数参数
func show(a interface{}) {
	fmt.Printf("type:%T value:%v\n", a, a)
}

func main() {
	var m1 map[string]interface{}
	m1 = make(map[string]interface{}, 16)
	m1["name"] = "李霞"
	m1["age"] = 18
	m1["merried"] = true
	m1["hobby"] = [...]string{"唱", "跳", "rap"}
	fmt.Println(m1)

	show(false)
	show(nil)
	show(m1)
}

从接口值中获取到对应的实际值需要使用类型断言,其语法格式如下。

x.(T)

其中:

  • x:表示接口类型的变量
  • T:表示断言x可能是的类型。

该语法返回两个参数,第一个参数是x转化为T类型后的变量,第二个值是一个布尔值,若为true则表示断言成功,为false则表示断言失败。

我想指定空接口接收的值具体是什么?

接口是一种类型,一种抽象的类型,它是一个只要求实现特定方法的抽象类型

package main

import (
	"fmt"
)

// 类型断言1
func assign(a interface{}) {
	fmt.Printf("%T\n", a)
	str, ok := a.(string)
	if !ok {
		fmt.Println("猜错了")
	} else {
		fmt.Println("传进来的是一个字符串:", str)
	}
}

// 类型断言2
func assign2(a interface{}) {
	fmt.Printf("%T\n", a)
	switch t := a.(type) {
	case string:
		fmt.Println("是一个字符串:", t)
	case int:
		fmt.Println("是一个int:", t)
	case int64:
		fmt.Println("是一个int64:", t)
	case bool:
		fmt.Println("是一个bool:", t)
	}
}

func main() {
	assign(100)
	assign2(true)
	assign2("学海无涯苦作舟")
	assign2(int64(200))
}