对Golang interface的理解

理解golang的interface主要在于如下两点:golang

  • interface是方法的集合
  • interface是一种类型

简单示例

package main

import "fmt"

type Animal interface {
    Speak() string
}

type Cat struct{}
func (c *Cat) Speak() string {
    return "cat"
}

type Dog struct{}
func (d Dog) Speak() string {
    return "dog"
}


func main() {
    animals := []Animal{Cat{}, Dog{}}
    for _, animal := range animals {
        fmt.Println(animal.Speak())
    }

}

以上代码中,定义了Animal为接口,而Cat和Dog两个结构体分别实现了接口中定义的方法。当interface{}做为函数形参时,能够接受不一样类型的参数。数组

若是将上述代码的:函数

func (c Cat) Speak() string {
    return "cat"
}

修改成:指针

func (c *Cat) Speak() string {
    return "cat"
}

再次运行源代码,就会出现如下错误:code

cannot use Cat literal (type Cat) as type Animal in array or slice literal:
Cat does not implement Animal (Speak method has pointer receiver)

这是由于程序认为Cat并未实现Speak()方法, 而是由 *Cat 实现的。这说明结构体在实现接口方法时并不会隐式转换类型。接口

可是:string

可是,把

animals := []Animal{Cat{}, Dog{}}

修改为

animals := []Animal{&Cat{}, &Dog{}}

却能够执行,由于把指针做为参数,会隐式转换。

interface 数组

interface{} 做为函数形参和 []interface{} 做为形参有很大区别,示例以下:it

interface{}

interface{} 能够赋值任何类型的值class

package main

import "fmt"

func Test(params interface{}) {
    fmt.Println(params)
}

func main() {

    Test("string")
    Test(123)
    Test(true)
}

[]interface{}

package main

import (
    "fmt"
)

func PrintAll(vals []interface{}) {
    for _, val := range vals {
        fmt.Println(val)
    }
}

func main() {
    names := []string{"stanley", "david", "oscar"}
    PrintAll(names)
}

以上代码是没法正常运行的,错误提示为:import

cannot use names (type []string) as type []interface {} in argument to PrintAll

这说明对接口数组赋值前,必须多一个类型转换操做,正确代码以下:

package main

import (
    "fmt"
)

func PrintAll(vals []interface{}) {
    for _, val := range vals {
        fmt.Println(val)
    }
}

func main() {
    names := []string{"stanley", "david", "oscar"}
    vals := make([]interface{}, len(names))
    for i, v := range names {
        vals[i] = v
    }
    PrintAll(vals)
}
相关文章
相关标签/搜索