26

golang接口基础用法

 4 years ago
source link: https://studygolang.com/articles/24976
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.

定义

接口是一组包含方法名,参数,返回值的未具体实现方法的集合

基础用法如下:

package main

import (
    "fmt"
)

type Schooler interface {
    Name() string
    Age() int
    Grade() int
}

type Student struct {
    name  string
    age   int
    grade int
}

func (s Student) Name() string {
    return s.name
}

func (s Student) Age() int {
    return s.age
}

func (s Student) Grade() int {
    return s.grade
}

func main() {
    var school Schooler
    student := Student{name: "Jack", age: 10, grade: 4}
    // 因为student实现了Schooler接口所以直接赋值没问题
    school = student
    fmt.Printf("name:%v,age:%v,grade:%v\n", school.Name(), school.Age(), school.Grade()) // name:Jack,age:10,grade:4
}

空接口

空接口不包含任何方法,因此, 任意类型均实现了空接口

任意类型变量都可以赋值给空接口类型的变量,如下所示:

package main

import (
    "fmt"
)

type Typer interface{}

func main() {
    var tt Typer
    var a int
    var b float32

    tt = a
    fmt.Printf("%T\n", tt) // int
    tt = b
    fmt.Printf("%T\n", tt) // float32
}

测试接口实现

测试变量是否实现了某个接口需要使用 x.(T) 的特定语法,如下所示:

package main

import (
    "fmt"
)

type Schooler interface {
    Name() string
    Age() int
}

type Student struct {
    name string
    age  int
}

type Teacher struct {
    name string
    age  int
}

func (s Student) Name() string {
    return s.name
}

func (s Student) Age() int {
    return s.age
}

func (s Teacher) Name() string {
    return s.name
}

func CheckSchoolerImpliments(v interface{}) bool {
    if tmp, ok := v.(Schooler); ok {
        fmt.Printf("%T, %v", tmp, tmp)
        return true
    }
    return false
}

func main() {
    student := Student{name: "Jack", age: 10}
    teacher := Teacher{name: "Lucy", age: 26}
    fmt.Println(CheckSchoolerImpliments(student)) // main.Student, {Jack 10}true
    fmt.Println(CheckSchoolerImpliments(teacher)) // false
}

类型断言

空接口可以存储任意类型,区分不同的类型常用两种方法, Comma-ok断言switch判断

package main

import (
    "fmt"
)

type Student struct {
    name string
}

func main() {
    var params = make([]interface{}, 3)
    fmt.Println(params) // [<nil> <nil> <nil>]
    params[0] = 18
    params[1] = "hello"
    params[2] = Student{name: "Jack"}
    fmt.Println(params) // [18 hello {Jack}]

    for _, item := range params {
        if _, ok := item.(int); ok {
            fmt.Printf("%v's type is int\n", item) // 18's type is int
        } else if _, ok := item.(string); ok {
            fmt.Printf("%v's type is string\n", item) // hello's type is string
        } else if _, ok := item.(Student); ok {
            fmt.Printf("%v's type is struct\n", item) // {Jack}'s type is struct
        }
    }

    for _, item := range params {
        switch value := item.(type) {
        case int:
            fmt.Printf("%v's type is int\n", value) // 18's type is int
        case string:
            fmt.Printf("%v's type is string\n", item) // hello's type is string
        case Student:
            fmt.Printf("%v's type is struct\n", item) // {Jack}'s type is struct
        default:
            fmt.Printf("unknown type\n")
        }
    }
}

接口零值

未赋值的接口类型为 nil

package main

import (
    "fmt"
)

type Student interface {
    name() string
}

func main() {
    var s Student
    if s == nil {
        fmt.Println("s is nil") // s is nil
    }
}

指针实现接口与值实现接口

package main

import (
    "fmt"
)

type Schooler interface {
    Name() string
    Age() int
}

type Student struct {
    name string
    age  int
}

type Teacher struct {
    name string
    age  int
}

func (s Student) Name() string {
    return s.name
}

func (s Student) Age() int {
    return s.age
}

func (s *Teacher) Name() string {
    return s.name
}

func (s *Teacher) Age() int {
    return s.age
}

func main() {
    student := Student{name: "Jack", age: 10}
    teacher := Teacher{name: "Lucy", age: 26}

    var s Schooler
    s = student
    fmt.Printf("name:%v.age:%v\n", s.Name(), s.Age()) // name:Jack.age:10
    // s = teacher // Teacher does not implement Schooler, *Teacher does
    s = &teacher
    fmt.Printf("name:%v.age:%v\n", s.Name(), s.Age()) //name:Lucy.age:26
}

接口嵌套

package main

import (
    "fmt"
)

type Peopler interface {
    Name() string
    Age() int
}

type Schooler interface {
    Peopler
    Role() string
}

type Student struct {
    name string
    age  int
}

type Teacher struct {
    name string
    age  int
}

func (s Student) Name() string {
    return s.name
}

func (s Student) Age() int {
    return s.age
}

func (s Student) Role() string {
    return "Student"
}

func main() {
    student := Student{name: "Jack", age: 10}

    var p Peopler
    var s Schooler
    p = student
    fmt.Printf("name:%v, age:%v\n", p.Name(), p.Age()) // name:Jack.age:10
    s = student
    fmt.Printf("name:%v, age:%v, role:%v\n", s.Name(), s.Age(), s.Role()) // name:Jack, age:10, role:Student
}

参考: https://studygolang.com/articles/20117


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK