Go语言接口(Interface)概念与应用 | 豆包MarsCode AI 刷题

78 阅读5分钟

Go语言接口(Interface)概念与应用

本文主要介绍了Go语言中的接口(interface)概念、特点和使用方法。以下是文档的重点内容概括:

1. 接口定义与实现

1.1 接口定义

接口定义了对象的行为规范,是一种抽象的类型,由具体对象实现规范细节。接口是方法签名的集合,如果一个类型的所有方法签名与接口中的匹配,则该类型实现了该接口,无需显式声明。

1.2 接口定义格式

以下是接口定义的格式和示例代码:

type MyInterface interface {
    Method1()
    Method2()
}

1.3 接口的定义与实现接口中的方法

案例

package main
import "fmt"

type Dog struct{}
type Cat struct {}

//声明一个接口并定义一个sleep方法
type sleeper interface {
    Sleep()
}
/**
    Dog实现了sleeper接口的Sleep方法,实现接口的方法非常简单,只要定义一个与接口中方法相同名称的方法,
    并指定一个接收者,看可以说该接收者实现了接口中的方法。
 */
func (d Dog) Sleep(){
    fmt.Println("狗在睡觉")
}
func (c Cat) Sleep(){
    fmt.Println("猫在睡觉")
}
func interfaceFn01(){
    d,c:=Dog{},Cat{}
    d.Sleep() // 狗在睡觉
    c.Sleep() // 猫在睡觉
}


func main()  {
    interfaceFn01()
}

image.png

2. 值接收者与指针接收者实现接口的区别

2.1 值接收者与指针接收者

值接收者可以是值类型或指针类型,而指针接收者必须是指针类型。以下是使用值接收者和指针接收者实现接口的示例代码:

type ValueReceiver interface {
    Method()
}

type MyValue struct {}

func (v MyValue) Method() {
    // 实现细节
}

type PointerReceiver interface {
    Method()
}

type MyPointer struct {}

func (p *MyPointer) Method() {
    // 实现细节
}

案例

package main
import "fmt"

type Dog struct{}
type Cat struct {}

/* 值接收者实现接口与指针接收者实现接口的区别*/
type Mover interface {
    move()
}
//值接收者实现接口
func (d Dog) move(){
    fmt.Println("值接收者实现接口")
}
//指针接收者实现接口
func (c *Cat) move(){
    fmt.Println("指针接收者实现接口")
}

func interfaceFn02(){
    var x Mover
    var y Mover
    dog01:=Dog{}
    x=dog01
    dog02:=&Dog{}
    x=dog02
    x.move()

    // cat01:=Cat{}
    // y=cat01 // 错误,y不能接收Cat{}类型,y只能接收&Cat{}类型
    cat02:=&Cat{}
    y=cat02
    y.move()
}

func main(){
    interfaceFn02()
}

image.png

3. 空接口

3.1 空接口定义

空接口没有定义任何方法,因此任何类型都实现了空接口。空接口类型的变量可以存储任意类型的值,可以作为函数参数接收任意类型的数据。

3.2 空接口使用示例

以下是空接口的使用示例,包括存储不同类型数据和作为函数参数:

var emptyInterface interface{}

emptyInterface = "string"
emptyInterface = 42

func processInterface(x interface{}) {
    // 处理x
}

案例

package main
import "fmt"
/**
    空接口:空接口是指没有定义任何方法的接口,因此任何类型都实现了空接口。空接口类型的变量可以存储任意类型的变量,
    空接口实现可以接收任意类型的函数参数(相当于Java的Object类型)。
 */
func interfaceFn03(){
    //定义空接口,任何类型都可以赋值给空接口
    var x interface{}
    s:="我是张三"
    x=s
    fmt.Println(x)
    num:=100
    x=num
    fmt.Println(x)
    b:=true
    x=b
    fmt.Println(x)

    //使用空接口作为函数的参数表示参数是任意类型
    fn:= func(arg interface{}) {
        fmt.Println(arg)
    }
    fn("参数") // 传入字符串
    fn(11) // 传入int类型
    fn(true) // 传入布尔类型

    //使用空接口作为map的value
    m:=make(map[string]interface{})
    m["name"]="张三"
    m["age"]=10
    m["isShow"]=true
    fmt.Println(m)

}
func main(){
    interfaceFn03()
}


image.png

4. 类型断言

4.1 类型断言概念

类型断言用于检查接口值中存储的值是否为特定的类型。类型断言的语法是 value, ok := x.(T),其中 x 是接口类型,T 是具体的类型或接口类型。

4.2 类型断言返回值

类型断言返回两个值:value(如果断言成功,则是转换后的值)和 ok(布尔值,表示断言是否成功)。

4.3 类型断言示例

以下是如何使用类型断言的示例,包括成功和失败的情况:

var x interface{} = "hello"

str, ok := x.(string)
if ok {
    fmt.Println(str)  // 输出:hello
} else {
    fmt.Println("not a string")
}

int, ok := x.(int)
if ok {
    fmt.Println(int)  // 不会执行,因为x不是int类型
} else {
    fmt.Println("not an int")
}

案例

package main
import "fmt"
/**
    类型断言:类型断言(Type Assertion)是一个使用在接口值上的操作,用于检查接口类型变量所持有的值是否实现了
    期望的接口或者具体的类型。类型断言语法格式为:value, ok := x.(T)。其中,x表示一个接口的类型,
    T表示一个具体的类型(也可为接口类型)。
    该断言表达式会返回 x 的值(也就是 value)和一个布尔值(也就是 ok),可根据该布尔值判断 x 是否为 T 类型(通过ok判断是否断言成功):
        (1).如果 T 是具体某个类型,类型断言会检查 x 的动态类型是否等于具体类型 T。
        如果检查成功,类型断言返回的结果是 x 的动态值,其类型是 T。
        (2).如果 T 是接口类型,类型断言会检查 x 的动态类型是否满足 T。如果检查成功,x 的动态值不会被提取,
        返回值是一个类型为 T 的接口值。
        (3).无论 T 是什么类型,如果 x 是 nil 接口值,类型断言都会失败。
 */
func interfaceFn04(){
    var x interface{}
    x="我是张三"
    /**
        将x断言为string类型,类型断言会返回两个参数,第一个参数是断言值(x)转化为T类型后的变量,
        第二个值是一个布尔值,若为true则表示断言成功,为false则表示断言失败。
     */
    v, ok := x.(string)
    if ok {
        fmt.Println("断言成功,value:",v) // 断言成功,value: 我叫z乘风
    }else{
        fmt.Println("断言失败")
    }

    //断言失败的例子,当断言值为nil时会导致断言失败
    var y interface{} // v的默认值是nil
    v1,ok1:=y.(string)
    if ok1 {
        fmt.Println("断言成功,value:",v1)
    }else{
        fmt.Println("断言失败") // 断言失败
    }
}

func main(){
    interfaceFn04()
}

image.png