编辑这个页面须要登录或更高权限!

Go 语言接口(Interfaces)

Go语言接口不同于其他语言。在Go语言中,该接口是一种自定义类型,用于指定一组一个或多个方法签名,并且该接口是抽象的,因此不允许您创建该接口的实例。但是您可以创建接口类型的变量,并且可以为该变量分配具有接口所需方法的具体类型值。换句话说,接口既是方法的集合,也是自定义类型。

如何创建接口?

在Go语言中,您可以使用以下语法创建接口:

type interface_name interface{

    //方法签名
}

例如:

//创建一个接口
type myinterface interface{
    // 方法
    fun1() int
    fun2() float64
}

此处,接口名称包含在type和interface关键字之间,方法签名包含在花括号之间。

如何实现接口?

在Go语言中,为了实现接口,必须实现接口中声明的所有方法。go语言接口是隐式实现的。与其他语言一样,它不包含实现接口的任何特定关键字。如下例所示:

// Golang程序说明如何
//实现接口
package main

import "fmt"

//创建一个接口
type tank interface {

    // 方法
    Tarea() float64
    Volume() float64
}

type myvalue struct {
    radius float64
    height float64
}

//实现方法
//桶的(Tank)接口
func (m myvalue) Tarea() float64 {

    return 2*m.radius*m.height + 2*3.14*m.radius*m.radius
}

func (m myvalue) Volume() float64 {

    return 3.14 * m.radius * m.radius * m.height
}

func main() {

    // 访问使用桶的接口
    var t tank
    t = myvalue{10, 14}
    fmt.Println("桶的面积 :", t.Tarea())
    fmt.Println("桶的容量:", t.Volume())
}

输出:

桶的面积 : 908
桶的容量: 4396

注意事项

  • 接口的零值为nil。

  • 当接口包含零个方法时,此类接口称为空接口。因此,所有类型都实现空接口。

    语法:

    interface{}
  • 接口类型:该接口有两种类型,一种是静态的,另一种是动态的。静态类型是接口本身,例如下面示例中的tank。但是接口没有静态值,所以它总是指向动态值。
    接口类型的变量,其中包含实现接口的类型的值,因此该类型的值称为动态值,而该类型是动态类型。又称具体值和具体类型。

    //说明Go程序的概念
    //动态值和类型
    package main
    
    import "fmt"
    
    //创建接口
    type tank interface {
    
        // 方法
        Tarea() float64
        Volume() float64
    }
    
    func main() {
    
        var t tank
        fmt.Println("tank interface值为: ", t)
        fmt.Printf("tank 的类型是: %T ", t)
    }

    输出:

    tank interface值为:  <nil>
    tank 的类型是: <nil>

    在上面的示例中,有一个名为tank的接口。在此示例中,fmt.Println("tank interface值为: ", t) 语句返回该接口的动态值,而 fmt.Printf("tank 的类型是: %T ", t) 语句返回该接口的动态类型,即nil,因为这里的接口不知道谁在实现它。

  • 类型断言:在Go语言中,类型断言是应用于接口值的操作。换句话说,类型断言是提取接口值的过程。

    语法:

    a.(T)

    在这里,a是接口的值或表达式,T是也称为类型断言的类型。类型断言用于检查其操作数的动态类型是否匹配已断言的类型。如果T是具体类型,则类型断言检查a的给定动态类型是否等于T,这里,如果检查成功进行,则类型断言返回a的动态值。否则,如果检查失败,则操作将出现panic异常。如果T是接口类型,则类型断言检查满足T的给定动态类型,这里,如果检查成功进行,则不提取动态值。

    //类型断言 
    package main 
      
    import "fmt"
      
    func myfun(a interface{}) { 
      
        //提取a的值
        val := a.(string) 
        fmt.Println("值为: ", val) 
    } 
    func main() { 
      
        var val interface { 
        } = "nhooo"
          
        myfun(val) 
    }

    输出:

    值为:  nhooo

    在上面的示例中,如果将val:= a。(string)语句更改为val:= a。(int),则程序会抛出panic异常。因此,为了避免此问题,我们使用以下语法:

    value, ok := a.(T)

    在这里,如果a的类型等于T,则该值包含a的动态值,并且ok将设置为true。并且如果a的类型不等于T,则ok设置为false并且value包含零值,并且程序不会抛出panic异常。如下面的程序所示:

    package main
    
    import "fmt"
    
    func myfun(a interface{}) {
        value, ok := a.(float64)
        fmt.Println(value, ok)
    }
    func main() {
    
        var a1 interface {
        } = 98.09
    
        myfun(a1)
    
        var a2 interface {
        } = "nhooo"
    
        myfun(a2)
    }

    输出:

    98.09 true
    0 false
  • 类型判断:在Go接口中,类型判断用于将接口的具体类型与case语句中提供的多种类型进行比较。它与类型声明类似,只是有一个区别,即大小写指定类型,而不是值。您还可以将类型与接口类型进行比较。如下例所示:

    package main
    
    import "fmt"
    
    func myfun(a interface{}) {
    
        //使用类型判断
        switch a.(type) {
    
        case int:
            fmt.Println("类型: int,值:", a.(int))
        case string:
            fmt.Println("\n类型: string,值: ", a.(string))
        case float64:
            fmt.Println("\n类型: float64,值: ", a.(float64))
        default:
            fmt.Println("\n类型未找到")
        }
    }

    输出:

    类型: string,值:  nhooo
    
    类型: float64,值:  67.9
    
    类型未找到
  • 接口的使用:当您想要在其中传递不同类型的参数的方法或函数中时,可以使用接口,就像Println()函数一样。或者,当多种类型实现同一接口时,也可以使用接口。

Golang 菜鸟教程
Golang 控制语句
Golang 函数 & 方法
Golang 结构体
Golang 切片 & 数组
Golang 字符串(String)
Golang 指针
Golang 接口
Golang 并发
Golang 异常(Error)
Golang 其他杂项