golang中级进阶(五):接口接收者、结构体多接口、接口嵌套、空接口类型断言使用细节

目录

一、结构体值接收者和指针接收者实现接口的区别

1. 值接收者

2. 指针接收者

二、结构体实现多接口

三、接口嵌套

四、空接口和类型断言使用细节


一、结构体值接收者和指针接收者实现接口的区别

1. 值接收者

如果结构体中的方法是值接收者,那么实例化后的结构体值类型和结构体指针类型都可以赋值给接口变量

package main

import "fmt"

// 结构体值接收者和指针接收者实现接口的区别
type Usber interface {
	Start()
	Stop()
}

//值接收者
type Phone struct {
	Name string
}

func (p Phone) Start() {
	fmt.Println(p.Name, "启动")
}

func (p Phone) Stop() {
	fmt.Println(p.Name, "关机")
}

func main() {
    // 值接收者 如果结构体中的方法是值接收者,那么实例化后的结构体值类型和结构体指针类型都可以赋值给接口变量
	var p1 = Phone{
		Name: "小米手机",
	}
	var p2 Usber = p1
	p2.Start() // 小米手机 启动
	p2.Stop()  // 小米手机 关机

	var p3 = &Phone{
		Name: "华为",
	}
	var p4 Usber = p3
	p4.Start() // 华为 启动
	p4.Stop()  // 华为 关机
}

2. 指针接收者

如果结构体中的方法是指针接收者,那么实例化后结构体指针类型都可以赋值给接口变量, 结构体值类型没法赋值给接口变量。

package main

import "fmt"

// 结构体值接收者和指针接收者实现接口的区别
type Usber interface {
	Start()
	Stop()
}

// 指针接收者
type Phone2 struct {
	Name string
}

func (p *Phone2) Start() {
	fmt.Println(p.Name, "指针接收者启动")
}

func (p *Phone2) Stop() {
	fmt.Println(p.Name, "指针接收者关机")
}

func main() {
    // 指针接收者 如果结构体中的方法是指针接收者,那么实例化后结构体指针类型都可以赋值给接口变量, 结构体值类型没法赋值给接口变量。
	/*
		错误示范
		var p5 = Phone2{
			Name: "错误",
		}
		var p6 Usber = p5 // Phone2 does not implement Usber (Start method has pointer receiver)
		p6.Start()
		p6.Stop()
	*/
	var p5 = &Phone2{
		Name: "魅族",
	}
	var p6 Usber = p5
	p6.Start() // 魅族 指针接收者启动
	p6.Stop()  // 魅族 指针接收者关机
}

二、结构体实现多接口

package main

import "fmt"

// 一个结构体实现多个接口
type Seter interface {
	setName(string)
}

type Geter interface {
	getName() string
}

type Dog struct {
	Name string
}

func (d *Dog) setName(name string) {
	d.Name = name
}

func (d Dog) getName() string {
	return d.Name
}

func main() {
    // 一个结构体实现多个接口
	var d1 = &Dog{
		Name: "小花",
	}
	var d2 Seter = d1
	d2.setName("大黄")
	var d3 Geter = d1
	fmt.Println(d3.getName()) // 大黄
}

三、接口嵌套

接口嵌套不用标点符号

package main

import "fmt"

// 接口嵌套
type Aer interface {
	Say()
}

type Ber interface {
	Move()
}

type Anyer interface { // 接口嵌套不用标点符号
	Aer
	Ber
}

type Cat struct {
	Name string
}

func (c Cat) Say() {
	fmt.Println(c.Name, "喵喵喵")
}

func (c Cat) Move() {
	fmt.Println(c.Name, "移动")
}

func main() {
    // 接口嵌套
	var c = Cat{
		Name: "猫猫",
	}

	var c1 Anyer = c
	c1.Say()  // 猫猫 喵喵喵
	c1.Move() // 猫猫 移动
}

四、空接口和类型断言使用细节

空接口是没有索引的,不允许[0]或者.xxx进行获取,解决方案使用类型断言进行获取。

package main

import "fmt"

// 空接口类型断言
type Address struct {
	Info  string
	Phone int
}

func main() {
    // 空接口类型断言使用细节
	var user = make(map[string]interface{})
	user["username"] = "张三"
	user["age"] = 20
	user["hobby"] = []string{"吃饭", "睡觉"}

	fmt.Println(user)          // map[age:20 hobby:[吃饭 睡觉] username:张三]
	fmt.Println(user["hobby"]) // [吃饭 睡觉]
	// 空接口是没有索引的,不允许下方这样调用
	//fmt.Println(user["hobby"][1]) // map index expression of type interface{}

	// 解决方案,使用类型断言
	hobby, ok := user["hobby"].([]string)
	if ok {
		fmt.Println(hobby[1]) // 睡觉
	}

	address := Address{
		Info:  "济南市",
		Phone: 15122332233,
	}
	user["address"] = address
	fmt.Println(user["address"]) // {济南市 15122332233}
	// 空接口是没有索引的,不允许下方这样调用
	//fmt.Println(user["address"].Info) // type interface{} has no field or method Info

	// 解决方案,同样使用类型断言
	userInfo, ok := user["address"].(Address)
	if ok {
		fmt.Println(userInfo.Info) // 济南市
	}
}

你可能感兴趣的:(进军golang,go,interface,struct,类型断言,接口嵌套)