Привет всем, меня зовут Мин.
Во время самостоятельного изучения Golang я написал подробные учебные заметки и разместил их в своем личном общедоступном аккаунте WeChat «Время программирования Go». вы только изучаете язык Go, уделяйте ему внимание, учитесь и развивайтесь вместе.
Мой онлайн-блог:golang.iswbm.comМой Github: github.com/iswbm/GolangCodingTime
1. Ограничения на вызовы методов
Интерфейс представляет собой фиксированный набор методов. Из-за ограничений статических типов переменные интерфейса иногда могут вызывать только определенные методы.
Пожалуйста, смотрите код ниже
package main
import "fmt"
type Phone interface {
call()
}
type iPhone struct {
name string
}
func (phone iPhone)call() {
fmt.Println("Hello, iPhone.")
}
func (phone iPhone)send_wechat() {
fmt.Println("Hello, Wechat.")
}
func main() {
var phone Phone
phone = iPhone{name:"ming's iphone"}
phone.call()
phone.send_wechat()
}
Я определил интерфейс телефона, и мне нужно только реализовать метод вызова, то есть до тех пор, пока устройство, которое может совершать вызов, является телефоном (это кажется бесполезной ерундой).
Затем определите структуру iPhone, которая получает два метода: один — сделать звонок (функция вызова), другой — отправить WeChat (функция send_wechat).
Последний шаг — ключевой, мы определяем объект телефона типа Интерфейс телефона, содержимым этого объекта является структура iPhone. Затем мы вызываем метод вызова этого объекта, и все работает нормально.
но когда ты звонишьphone.send_wechat
метод, программа сообщит об ошибке, подсказав нам, что метод типа Phone не имеет поля или метода send_wechat.
# command-line-arguments
./demo.go:30:10: phone.send_wechat undefined (type Phone has no field or method send_wechat)
Причина также очевидна, потому что наш объект телефона явно объявлен как тип интерфейса Phone, поэтому методы, вызываемые телефоном, будут ограничены этим интерфейсом.
Так как же телефон может вызвать метод send_wechat?
Ответ заключается в том, что его можно объявить как тип интерфейса Phone, но должно быть ясно, что объект phone на самом деле неявно реализует интерфейс Phone, так что вызовы методов не будут ограничены типом интерфейса.
Измените основной метод следующим образом.
func main() {
phone := iPhone{name:"ming's iphone"}
phone.call()
phone.send_wechat()
}
После запуска все нормально, ошибок не выдает.
Hello, iPhone.
Hello, Wechat.
2. Неявное преобразование при вызове функции
Вызовы функций в языке Go передаются по значению, а тип переменных преобразуется перед вызовом метода.
Например следующий код
import (
"fmt"
)
func printType(i interface{}) {
switch i.(type) {
case int:
fmt.Println("参数的类型是 int")
case string:
fmt.Println("参数的类型是 string")
}
}
func main() {
a := 10
printType(a)
}
Если вы запустите его, вы обнаружите, что все нормально
参数的类型是 int
Но если вы переместите содержимое внутри функции наружу
package main
import "fmt"
func main() {
a := 10
switch a.(type) {
case int:
fmt.Println("参数的类型是 int")
case string:
fmt.Println("参数的类型是 string")
}
}
Будут неожиданные результаты, и будет сообщено об ошибке.
# command-line-arguments
./demo.go:9:5: cannot type switch on non-interface value a (type int)
Эта операция запутает новичка, логика кода одинакова, почему один не сообщит об ошибке, а другой сообщит об ошибке?
Причина на самом деле довольно проста.
Когда функциональный интерфейс interface{} является пустым типом интерфейса, мы говорим, что он может принимать параметры любого типа (в реках и озерах это называется без трюков).
Когда вы используете этот способ написания, Go молча делает для нас одну вещь, а именно неявно преобразует тип значения параметра, переданного в функцию (примечание: вызовы функций в языке Go передаются по значению) в interface {} Типы.
Как выполнить явное преобразование типов интерфейса
Поняв неявное преобразование типа интерфейса в функции, у вас могут начаться вопросы: я использую утверждение типа, которое может быть реализовано только функцией получения пустого типа интерфейса?
Ответ конечно же Нет.
Если вы хотите вручную привести его к типу, вы можете преобразовать статический тип переменной a в тип interface{} и присвоить его b (в настоящее время статический тип a все еще int, а статический тип b — interface{ })
var a int = 25
b := interface{}(a)
Зная метод, измените код следующим образом:
package main
import "fmt"
func main() {
a := 10
switch interface{}(a).(type) {
case int:
fmt.Println("参数的类型是 int")
case string:
fmt.Println("参数的类型是 string")
}
}
После запуска все работает нормально.
参数的类型是 int
3. Неявные преобразования в утверждениях типа
Как мы видели выше, только объекты, статический тип которых является типом интерфейса, могут выполнять утверждение типа.
Когда утверждение типа будет завершено, он вернет объект, чей статический тип является типом, который вы утвердили.То есть, когда мы используем утверждение типа, Go фактически выполнит для нас неявное преобразование типа по умолчанию.
Метод проверки также очень прост: после однократного использования утверждения типа снова используйте утверждение типа на возвращаемом объекте, и Голанд сразу подскажет нам, что новый объект b не является объектом интерфейсного типа, и утверждение типа не разрешено. .