31. Расскажите о пустых интерфейсах в Go

Go

Привет всем, меня зовут Мин.

В период самостоятельного изучения Golang я написал подробные учебные заметки и разместил их в своем личном общедоступном аккаунте WeChat «Время программирования на Go».Что касается языка Go, я тоже новичок, поэтому то, что я написал, должно больше подходить для новых студентов, если вы только изучаете язык Go, вам стоит обратить на него внимание, учиться и расти вместе.

Мой онлайн-блог:golang.iswbm.comМой Github: github.com/iswbm/GolangCodingTime


1. Что такое пустой интерфейс?

Пустой интерфейс — это особая форма типа интерфейса.Обычные интерфейсы имеют методы, но пустые интерфейсы не определяют никаких портов методов.Поэтому можно сказать, что все типы реализуют как минимум пустые интерфейсы.

type empty_iface interface {
}

Каждый интерфейс содержит два свойства: одно — значение, а другое — тип.

Для пустых интерфейсов оба равны нулю, вы можете использовать fmt для проверки

package main

import (
    "fmt"
)

func main() {
    var i interface{}
    fmt.Printf("type: %T, value: %v", i, i)
}

Вывод выглядит следующим образом

type: <nil>, value: <nil>

2. Как использовать пустой интерфейс?

Первый, обычно мы будем напрямую использоватьinterface{}Экземпляр объявлен как тип, и этот экземпляр может содержать значения любого типа.

package main

import (
    "fmt"
)

func main()  {
    // 声明一个空接口实例
    var i interface{}

    // 存 int 没有问题
    i = 1
    fmt.Println(i)

    // 存字符串也没有问题
    i = "hello"
    fmt.Println(i)

    // 存布尔值也没有问题
    i = false
    fmt.Println(i)
}

второй, если вы хотите, чтобы ваша функция получала значение любого типа, вы также можете использовать пустой интерфейс

Получает значение любого типа Пример

package main

import (
    "fmt"
)

func myfunc(iface interface{}){
    fmt.Println(iface)
}

func main()  {
    a := 10
    b := "hello"
    c := true

    myfunc(a)
    myfunc(b)
    myfunc(c)
}

Получить любое количество значений любого типа Пример

package main

import (
    "fmt"
)

func myfunc(ifaces ...interface{}){
    for _,iface := range ifaces{
        fmt.Println(iface)
    }
}

func main()  {
    a := 10
    b := "hello"
    c := true

    myfunc(a, b, c)
}

третий, вы также определяете массив, слайс, карту, strcut, которые могут принимать любой тип, например, здесь определите слайс

package main

import "fmt"

func main() {
    any := make([]interface{}, 5)
    any[0] = 11
    any[1] = "hello world"
    any[2] = []int{11, 22, 33, 44}
    for _, value := range any {
        fmt.Println(value)
    }
}

3. Несколько ям, на которые стоит обратить внимание в пустом интерфейсе

яма 1: Пустой интерфейс может содержать любое значение, но это не означает, что любой тип может содержать значение пустого типа интерфейса.

С точки зрения реализации значение любого типа удовлетворяет пустому интерфейсу. Следовательно, пустой тип интерфейса может содержать любое значение, а также может принимать исходное значение из пустого интерфейса.

Но если вы присвоите объект пустого типа интерфейса объекту фиксированного типа (например, int, string и т. д.), будет сообщено об ошибке.

package main

func main() {
    // 声明a变量, 类型int, 初始值为1
    var a int = 1

    // 声明i变量, 类型为interface{}, 初始值为a, 此时i的值变为1
    var i interface{} = a

    // 声明b变量, 尝试赋值i
    var b int = i
}

Эта ошибка как то, что можно положить в подарочную коробку, это точно можно положить в контейнер, но и наоборот, вещи, которые можно положить в контейнер, нельзя положить в подарочную коробку, это прямо запрещено в Go. Обратная операция. (утверждение: Должны быть другие причины лежащего в основе принципа, но новичкам это объяснение может быть легче понять. )

.\main.go:11:6: cannot use i (type interface {}) as type int in assignment: need type assertion

Яма 2:: После того, как пустой интерфейс содержит массивы и слайсы, объект больше не может быть слайсирован.

package main

import "fmt"

func main() {
    sli := []int{2, 3, 5, 7, 11, 13}

    var i interface{}
    i = sli

    g := i[1:3]
    fmt.Println(g)
}

Выполнение сообщит об ошибке.

.\main.go:11:8: cannot slice i (type interface {})

яма 3: когда вы используете пустой интерфейс для получения параметров любого типа, его статический тип — interface{}, но мы не знаем динамический тип (это int, string или что-то еще), поэтому вам нужно использовать утверждение типа .

package main

import (
    "fmt"
)

func myfunc(i interface{})  {

    switch i.(type) {
    case int:
        fmt.Println("参数的类型是 int")
    case string:
        fmt.Println("参数的类型是 string")
    }
}

func main() {
    a := 10
    b := "hello"
    myfunc(a)
    myfunc(b)
}

Вывод выглядит следующим образом

参数的类型是 int
参数的类型是 string