Почему я получаю ошибку invalid operation: err (variable of type Error) is not an interface при проверке типа переменной?
Я пытаюсь проверить, реализует ли переменная err интерфейс error.
В данном коде видно что err является экземпляром MyError, который реализует метод Error.
Насколько я понимаю реализация метода Error является достаточным для того чтобы имплементировать интерфейс в Go.
Скажите почему я получаю ошибку?
package main import "fmt" type MyError struct { Message string } func (e MyError) Error() string { return e.Message } func main() { err := MyError{"Something went wrong"} // Проверяем, реализует ли err интерфейс error if _, ok := err.(error); ok { fmt.Println("err реализует интерфейс error") } else { fmt.Println("err НЕ реализует интерфейс error") } } |
package main import "fmt" type MyError struct { Message string } func (e MyError) Error() string { return e.Message } func main() { err := MyError{"Something went wrong"} // Проверяем, реализует ли err интерфейс error if _, ok := err.(error); ok { fmt.Println("err реализует интерфейс error") } else { fmt.Println("err НЕ реализует интерфейс error") } }
Консольный вывод:
vlad@DESKTOP:~/go/src/project$ go run cmd/structure/main.go # command-line-arguments cmd/structure/main.go:17:14: invalid operation: err (variable of type MyError) is not an interface |
vlad@DESKTOP:~/go/src/project$ go run cmd/structure/main.go # command-line-arguments cmd/structure/main.go:17:14: invalid operation: err (variable of type MyError) is not an interface
https://go.dev/play/p/AN2_V0ozTpL
Дополнительно:
https://go.dev/play/p/eDi3J3Zzcdg
package main import "fmt" type MyError struct { Message string } func (e MyError) Error() string { return e.Message } func (e MyError) Smth() { } type SomeInterface interface { Smth() } func main() { var err SomeInterface err = MyError{"Something went wrong"} // Проверяем, реализует ли err интерфейс error if _, ok := err.(error); ok { fmt.Println("err реализует интерфейс error") } else { fmt.Println("err НЕ реализует интерфейс error") } } |
package main import "fmt" type MyError struct { Message string } func (e MyError) Error() string { return e.Message } func (e MyError) Smth() { } type SomeInterface interface { Smth() } func main() { var err SomeInterface err = MyError{"Something went wrong"} // Проверяем, реализует ли err интерфейс error if _, ok := err.(error); ok { fmt.Println("err реализует интерфейс error") } else { fmt.Println("err НЕ реализует интерфейс error") } }
У вас получилось, что тип переменной err это структура, но нужно чтобы тип был каким-нибудь интерфейсом.
В моем примере я создал интерфейс SomeInterface и добавил вашему типу метод, чтобы он этому интерфейсу удовлетворял. Теперь данный ассершн имеет смысл.
P.S. С пустым интерфейсом тоже работать будет https://go.dev/play/p/Yz0M1Wzopua
Я полностью присоединюсь к ответу выше, просто хочу дополнить.
Замечу, что вы проверяете не то, что нужно, шиворот-навыворот. Проверять при приведении типов лучше конкретные типы. Т.е. мы получаем из функции ошибку в виде интерфейса error, а уже в проверке проверяем её на наш кастомный тип MyError. Поэтому желательно (не обязательно) не проверять переменную ошибки в той же функции, где вы её создали, а возвращать откуда-то и уже тогда проверять на ошибку.
К тому же, если у вас вопросы по этой теме, я настоятельно хочу порекомендовать правильно использовать кастомные типы ошибок, и даже если указатель на ваш кастомный тип ошиьбки равен nil, то ни в коем случае не возвращайте сам этот указатель, а возвращайте буквально nil. Так вы избавитесь от тысяч выстрелов себе в ногу.
package main import ( "fmt" ) type MyError struct { Message string } func (e MyError) Error() string { return e.Message } func main() { // Возвращаем из функции нашу кастомную ошибку, но в виде интерфейса error err := foo() if err == nil { fmt.Println("Нет ошибки") // И теперь тут приводим error к нашему типу MyError и проверяем } else if myErr, ok := err.(MyError); ok { fmt.Printf("Ура! Нужный нам тип ошибки: %vn", myErr.Message) } else { fmt.Println("Какой-то другой тип ошибки:", err) } // Проверка одной из "подстав" Go err = bad() if err != nil { fmt.Println("Упс... Как так... Не nil...") } else { fmt.Println("Должно вывестись это, но не выводится...") } err = good() if err != nil { fmt.Println("Это не должно выводиться, всё верно.") } else { fmt.Println("Ошибки нет, всё верно.") } } func foo() error { err := MyError{"Ой! Ошибка MyError!"} // err := fmt.Errorf("Ой! Обычная ошибка!") // var err error = nil return err } func bad() error { var p *MyError = nil // Вроде же nil, но не работает.... // p = &MyError{"Ой!"} // Пробуем создать ошибку, и всё работает. if p == nil { fmt.Println("Ну nil же-ж... Должно же-ж работать", p) } return p } func good() error { // return MyError{"Ой!"} // Буквально пишем "nil", никаких указателей, которые равны nil, это прямой выстрел в ногу return nil } |
package main import ( "fmt" ) type MyError struct { Message string } func (e MyError) Error() string { return e.Message } func main() { // Возвращаем из функции нашу кастомную ошибку, но в виде интерфейса error err := foo() if err == nil { fmt.Println("Нет ошибки") // И теперь тут приводим error к нашему типу MyError и проверяем } else if myErr, ok := err.(MyError); ok { fmt.Printf("Ура! Нужный нам тип ошибки: %vn", myErr.Message) } else { fmt.Println("Какой-то другой тип ошибки:", err) } // Проверка одной из "подстав" Go err = bad() if err != nil { fmt.Println("Упс... Как так... Не nil...") } else { fmt.Println("Должно вывестись это, но не выводится...") } err = good() if err != nil { fmt.Println("Это не должно выводиться, всё верно.") } else { fmt.Println("Ошибки нет, всё верно.") } } func foo() error { err := MyError{"Ой! Ошибка MyError!"} // err := fmt.Errorf("Ой! Обычная ошибка!") // var err error = nil return err } func bad() error { var p *MyError = nil // Вроде же nil, но не работает.... // p = &MyError{"Ой!"} // Пробуем создать ошибку, и всё работает. if p == nil { fmt.Println("Ну nil же-ж... Должно же-ж работать", p) } return p } func good() error { // return MyError{"Ой!"} // Буквально пишем "nil", никаких указателей, которые равны nil, это прямой выстрел в ногу return nil }
https://go.dev/play/p/2YcWcH9oqel
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
Ошибка "invalid operation: err (variable of type Error) is not an interface" возникает, когда вы пытаетесь использовать оператор проверки типа переменной для переменной, которая не является интерфейсом.
В языке программирования PHP оператор проверки типа переменной (instanceof) используется для определения, принадлежит ли объект к определенному классу или интерфейсу. Однако, если вы пытаетесь использовать этот оператор для переменной типа Error, который не является интерфейсом, то возникает ошибка "invalid operation: err (variable of type Error) is not an interface".
Чтобы исправить эту ошибку, вам необходимо использовать другой способ проверки типа переменной для типа данных Error. Вы можете использовать функцию is_a(), которая проверяет, является ли объект экземпляром класса или интерфейса. Например:
$error = new Error(); if (is_a($error, 'Error')) { echo 'This is an instance of Error class'; } else { echo 'This is not an instance of Error class'; }
Таким образом, используя функцию is_a() вместо оператора instanceof, вы сможете успешно проверить тип переменной типа Error без возникновения ошибки "invalid operation: err (variable of type Error) is not an interface".