接口(interface)的用法和介绍
golang 中的接口(interface)
- golang 中的接口是一种抽象数据类型,golang 中接口定义了对象的行为规范,只定义规范不实现。接口中定义的规范由具体的对象来实现
- 通俗的讲接口就一个标准,它是对一个对象的行为和规范进行约定,约定实现接口的对象必须得按照接口的规范
golang 中的接口(interface)的定义
- 在 golang 中接口(interface)是一种类型,一种抽象的类型。接口(interface)是一组 函数 method的集合,golang 中的接口不能包含任何变量
- 在 golang 中接口中的所有方法都没有方法体,接口定义了一个对象的行为规范,只定义规范不实现。接口体现了程序设计的多态和高内聚低耦合的思想
- 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
}