一架梯子,一头程序猿,仰望星空!

go语言Interface接口


go语言接口(interface),类似其他语言的接口的作用,主要用于定义一组函数(方法)签名,不包括实现。

1.接口定义

语法:

type 接口类型名 interface {
    函数签名列表
}

例子:

// 定义Abser接口类型,里面包含一个Abs函数签名定义,不包括函数实现。
type Abser interface {
    Abs() float64
}

2.接口实现

go语言实现接口,采用的是隐式实现方式,一个类(结构体)实现了某个接口类型,并不会像java之类的语言,显式的通过一个implement关键词说明实现了什么接口。

在go语言中一个类,只要实现了接口中的方法,就认为实现了接口,并不需要显式的声明类实现了什么接口。

例子:

package main

import (
    "fmt"
    "math"
)

// 定义Abser接口类型,里面包含一个Abs函数签名定义,不包括函数实现。
type Abser interface {
    Abs() float64
}

// 定义一个MyFloat类型,它是float64的别名
type MyFloat float64

// 给MyFloat类型,定义一个Abs方法,计算绝对值
func (f MyFloat) Abs() float64 {
    if f < 0 {
        return float64(-f)
    }
    return float64(f)
}

// 定义Vertex类型结构体
type Vertex struct {
    X, Y float64
}

// 为Vertex类型定义Abs方法
func (v *Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func main() {
    // 定义Abser接口变量
    var abser Abser

    // 定义MyFloat类型变量
    f := MyFloat(-100.25)

    // 因为MyFloat实现了,Abser接口中定义的方法,所以可以赋值给接口类型变量
    abser = f

    // 通过接口类型调用方法
    fmt.Println(abser.Abs())

    // 定义Vertex类型变量
    v := Vertex{10,20}

    // 将Vertex变量赋值给接口类型,这里之所以需要取地址符,因为*Vertex类型实现了接口的Abs方法
    abser = &v

    // 通过接口类型调用方法
    fmt.Println(abser.Abs())
}

运行输出:

100.25
22.360679774997898

说明:

MyFloat和Vertex并没有显式的说明实现Abser接口,只要实现了Abser接口的方法,就认为实现了Abser接口

提示:go语言中,可以给类型定义方法(函数),并不是只能给struct类型定义方法。

3.接口变量默认值

没有初始化的接口变量,默认值是nil

var abser Abser
if abser == nil {
    fmt.Println("is nil")
}

4.空接口

包含0个方法的接口,就是空接口。

空接口语法:

interface{}

空接口类型变量可以存储任意类型的数据,类似java的object类型。

例子:

package main

import "fmt"

func main() {
    // 定义空接口变量
    var i interface{}

    // 赋值一个Int类型数据给空接口
    i = 42

    fmt.Println(i)

    // 再赋值一个string类型数据给空接口
    i = "hello"
    
    fmt.Println(i)
}

运行输出:

42
hello

4.1.interface类型转换

例如,当我们将一个int类型的数据,赋值给interface{}类型变量后,怎么将interface{}类型转换回int类型?

转换语法:

t := i.(T)

i 是interface{}类型变量,T是我们要转换的类型

例子:

// 定义一个interface{}类型,并初始化为字符串
var i interface{} = "hello"

// 转换成string类型
s := i.(string)

注意:interface{}类型转换,只能转换至真实的类型,通俗的讲就是,当初赋值给interface{}变量的是什么类型数据,就只能还原成什么类型数据。

4.2.判断Interface类型转换失败

语法:

t, ok := i.(T)

通过第二个返回值ok判断是否转换成功

例子:

var i interface{} = "hello"

s, ok := i.(string)

4.3.interface类型判断

通过switch语句结合i.(type)语法,判断interface类型。

package main

import "fmt"

func do(i interface{}) {
    // 通过switch判断i的类型
    switch v := i.(type) {
    case int:
        fmt.Println("是int类型,", v)
    case string:
        fmt.Println("是string类型,", v)
    default:
        fmt.Println("未知类型,", v)
    }
}

func main() {
    do(21)
    do("hello")
    do(true)
}

运行输出:

是int类型 21
是string类型 hello
未知类型 true

主要: type语法只能用在switch语句中。