接口(interface)的用法和介绍

golang 中的接口(interface)

  1. golang 中的接口是一种抽象数据类型,golang 中接口定义了对象的行为规范,只定义规范不实现。接口中定义的规范由具体的对象来实现
  2. 通俗的讲接口就一个标准,它是对一个对象的行为和规范进行约定,约定实现接口的对象必须得按照接口的规范

golang 中的接口(interface)的定义

  1. 在 golang 中接口(interface)是一种类型,一种抽象的类型。接口(interface)是一组 函数 method的集合,golang 中的接口不能包含任何变量
  2. 在 golang 中接口中的所有方法都没有方法体,接口定义了一个对象的行为规范,只定义规范不实现。接口体现了程序设计的多态和高内聚低耦合的思想
  3. golang 中的接口也是一种数据类型,不需要显示实现。只需要一个变量含有接口类型 中的所有方法,那么这个变量就实现了这个接口
type 接口名 interface{
	方法名 1( 参数列表 1 ) 返回值列表 1
	方法名 2( 参数列表 2 ) 返回值列表 2 
	......
}
1.使用 type 将接口定义为自定义的类型名。Go 语言的接口在命名时,一般会在单词后面添加 er,如有写操作的接口叫 Writer,有字符串功能的接口叫 Stringer 等,接口名最好要能突出该接口的类型含义
2.方法名:当方法名首字母是大写且这个接口类型名首字母也是大写时,这个方法可以被接口所在的包(packge)之外的代码访问。
3.参数列表、返回值列表:参数列表和返回值列表中的参数变量名可以省略
import (
	"fmt"
	"testing"
)

//接口是一个规范
type Usber interface {
	Start()
	Stop()
}

//如果接口里面有方法的话,必须通过结构体或者通过自定义类型实现这个接口
type Phone struct {
	Name string
}

//手机要实现usb接口的话必须实现usb接口中的所有方法
func (p Phone) Start() {
	fmt.Println(p.Name, "手机启动")
}
func (p Phone) Stop() {
	fmt.Println(p.Name, "手机关机")
}
func (p Phone) Running() {
	fmt.Println(p.Name, "手机运行中...")
}

type Camera struct {
	Name string
}

func (c Camera) Start() {
	fmt.Println(c.Name, "相机启动")
}
func (c Camera) Stop() {
	fmt.Println(c.Name, "相机关机")
}
type Computer struct {
}

func (co Computer) Work(usber Usber) {
	usber.Start()
	usber.Stop()
}
//测试方法1
func TestInterface(t *testing.T) {
	p := Phone{
		Name: "小米",
	}
	var p1 Usber //golang中接口就是一个数据类型
	p1 = p       //表示手机实现Usb接口,必须实现接口定义 的所有方法
	p1.Start()   //小米 手机启动
	p1.Stop()    // 小米 手机关机
	//p1.Running() error p1.Running undefined (type Usber has no field or method Running)
	p.Running()
	c := Camera{
		Name: "佳能",
	}
	var c1 Usber
	c1 = c
	c1.Start() //佳能 相机启动
	c1.Stop()  // 佳能 相机关机
}
//测试方法1
func TestComputerInterface(t *testing.T) {
	var co = Computer{}
	var p = Phone{
		Name: "华为",
	}
	var c = Camera{
		Name:"尼康",
	}
	co.Work(p)//华为 手机启动 华为 手机关机
	co.Work(c)//尼康 相机启动 尼康 相机关机
}

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

值接收者

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

type Ber interface {
	GetName() string
}
type D struct {
	Name string
}
func (d D) GetName() string {
	return d.Name
}
func TestNestInterface(t *testing.T) {
	var d = D{ 
		Name: "Dog",
	}
	var b Ber = d
	fmt.Println(b.GetName())//Cat
}

指针接收者

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

type Aer interface {
	SetName(string)
}
type D struct {
	Name string
}
func (d *D) SetName(name string) { //指针类型
	d.Name = name
}
func TestNestInterface(t *testing.T) {
	/*错误写法
	var d = D{ 
		Name: "Dog",
	}*/
	//正确写法
	var d = &D{ 
		Name: "Dog",
	}
	var a Aer = d
	a.SetName()
}

一个结构体实现多个接口

type Aer interface {
	SetName(string)
}
type Ber interface {
	GetName() string
}
type D struct {
	Name string
}

func (d *D) SetName(name string) { //指针类型接口
	d.Name = name
}
func (d D) GetName() string {
	return d.Name
}
func TestNestInterface(t *testing.T) {
	var d = &D{ //
		Name: "Dog",
	}
	var a Aer = d
	var b Ber = d
	a.SetName("pig")
	fmt.Println(b.GetName())//pig
}

接口嵌套

接口与接口间可以通过嵌套创造出新的接口

type Aer interface {
	SetName(string)
}
type Ber interface {
	GetName() string
}
type Cer interface {
	Aer
	Ber
}

type D struct {
	Name string
}

func (d *D) SetName(name string) { //指针类型接口
	d.Name = name
}
func (d D) GetName() string {
	return d.Name
}

func TestNestInterface(t *testing.T) {
	var d = &D{ 
		Name: "Dog",
	}
	fmt.Println(d.GetName())//Dog
	var c Cer = d
	c.SetName("Cat")
	fmt.Println(c.GetName())//Cat
}