English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Основной курс Golang

Управляющие операторы в Golang

Функции и методы в Golang

Структуры в Golang

Срезы и массивы в Golang

Строки (String) в Golang

Указатели в Golang

Интерфейсы в Golang

Конкурентное программирование в Golang

Исключения (Error) в Golang

Другие темы Golang

Интерфейсы (Interfaces) языка Go

Интерфейс в 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 {
    возвратить 2*m.radius*m.height + 2*3.14*m.radius*m.radius
}
func (m myvalue) Volume() float64 {
    возвратить 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 { 
        }= "w3codebox"
          
        myfun(val) 
    }

    Вывод:

    Значение: w3codebox

    В предыдущем примере, если изменитьval := a.(string)Условие изменяется наval := a.(int)Если это так, то программа выбросит исключение panic. Поэтому, чтобы избежать этой проблемы, мы используем следующий синтаксис:

    value, ok := a.(T)

    Здесь, если тип a равен T, то это значение содержит динамическое значение a, и ok устанавливается в true. И если тип a не равен T, то ok устанавливается в false, и значение содержит нулевое значение, и программа не выбрасывает исключение 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 {
        }= "w3codebox"
        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, значение: w3codebox
    Тип: float64, значение: 67.9
    Тип не найден
  • Использование интерфейса:Когда вам нужно передавать различные типы параметров в методе или функции, вы можете использовать интерфейс, например, как функция Println(). Или, когда несколько типов реализуют один и тот же интерфейс, также можно использовать интерфейс.