38

Go 之 interface接口理解

 4 years ago
source link: https://www.tuicool.com/articles/EzI7bqa
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

go语言并没有面向对象的相关概念,go语言提到的接口和java、c++等语言提到的接口不同,它不会显示的说明实现了接口,没有继承、子类、implements关键词。go语言通过隐性的方式实现了接口功能,相对比较灵活。

interface是go语言的一大特性,主要有以下几个特点:

  • interface 是方法或行为声明的集合
  • interface接口方式实现比较隐性,任何类型的对象实现interface所包含的全部方法,则表明该类型实现了该接口。
  • interface还可以作为一中通用的类型,其他类型变量可以给interface声明的变量赋值。
  • interface 可以作为一种数据类型,实现了该接口的任何对象都可以给对应的接口类型变量赋值。

下面是一些代码示例

接口实现

package main

import "fmt"

type Animal interface {
    GetAge() int32
    GetType() string
}

type Dog struct {
    Age  int32
    Type string
}

func (a *Dog) GetAge() int32 {
    return a.Age
}
func (a *Dog) GetType() string {
    return a.Type
}

func main() {
    animal := &Dog{Age: 20, Type: "DOG"}
    fmt.Printf("%s max age is: %d", animal.GetType(), animal.GetAge())

}

interface作为通用类型

package main

import (
   "fmt"
   "reflect"
)

type User struct {
   Id     int
   Name   string
   Amount float64
}


func main() {
   var i interface{}
   i = "string"
   fmt.Println(i)
   i = 1
   fmt.Println(i)
   i = User{Id: 2}
   //i.(User).Id = 15  //运行此处会报错,在函数中修改interface表示的结构体的成员变量的值,编译时遇到这个编译错误,cannot assign to i.(User).Id
   fmt.Println(i.(User).Id)
  }

interface接口查询

接口查询,在一个接口变量中,查询所赋值的对象有没有实现其他接口所有的方法的过程,就是查询接口。即接口A实现了接口B中所有的方法,那么通过查询赋值A可以转化为B。

代码示例

package main

import "fmt"

type Animal interface {
    GetAge() int32
    GetType() string
}
type AnimalB interface {
    GetAge() int32
}

type Dog struct {
    Age  int32
    Type string
}

func (a *Dog) GetAge() int32 {
    return a.Age
}
func (a *Dog) GetType() string {
    return a.Type
}

func main() {
    var animal Animal = &Dog{Age: 20, Type: "DOG"}
    fmt.Printf("%s max age is: %d", animal.GetType(), animal.GetAge())
    var animalb AnimalB = &Dog{Age: 20, Type: "DOG"}
    fmt.Printf("max age is: %d", animalb.GetAge())

    //这里实现了animalb 转化Animal接口
    val, ok := animalb.(Animal)
    if !ok {
        fmt.Println("ok")
    } else {
        fmt.Printf("%s max age is: %d", val.GetType(), val.GetAge())
    }
}

接口转化很简单

val, ok := animalb.(Animal)

注意,animalb 只有AnimalB所包含的方法GetAge()。

如果接口A的方法列表是接口B的方法列表的子集,那么接口B可以赋值给接口A,反之则不行。

接口类型查询

只能对interface{}类型的变量使用类型查询

示例

package main

import "fmt"

type Animal interface {
    GetAge() int32
    GetType() string
}
type AnimalB interface {
    GetAge() int32
}

type Dog struct {
    Age  int32
    Type string
}

func (a *Dog) GetAge() int32 {
    return a.Age
}
func (a *Dog) GetType() string {
    return a.Type
}

func main() {
    var i interface{}
    //i = "ok"
    //方法一
    val, ok := i.(Animal)
    if !ok {
        fmt.Println("no")
    } else {
        fmt.Println(val.GetAge())
    }
    // 方法二
    switch val := i.(type) {
    case string:
        fmt.Println(val)
    case int:
        fmt.Println(val)
    default:
        fmt.Println(val)
    }
    // 方法三 通过反射
    typename := reflect.TypeOf(i)
    fmt.Println(typename)
}

interface默认nil所以查出是nil,如果给i赋值一个字符型值(去掉i = "ok"前面的注释),则返回

no

ok

string

参考:

https://blog.csdn.net/hzwy23/...

https://www.cnblogs.com/zhang...

links


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK