2015-04-06 3 views
1

Во-первых, я не совсем уверен, что если эта проблема более актуальна для ошибок, или взаимодействовать в GoLangGoLang Error/Механизм интерфейса

Я догоняет по GoLang следуя учебник. В этот урок встал вопрос page

Это основная демонстрация интерфейса ошибки. Когда я изменить код немного, как это, я запуталась:

package main 

import (
    "fmt" 
    "time" 
) 

type MyError struct { 
    When time.Time 
    What string 
} 

func (e *MyError) Error() string { 
    return fmt.Sprintf ("at %v, %s", e.When, e.What) 
} 

func run() *MyError { 
    return &MyError{ 
     time.Now(), "it didn't work", 
    } 
} 

func main() { 
    if err := run(); err != nil { 
     fmt.Println(err) 
    } 
    err1 := MyError{time.Now(), "it works again"} 
    fmt.Println(err1) 
    fmt.Println(err1.Error()) 
} 

Выход этой части кода:

at 2015-04-06 15:00:07.1541719 +0800 CST, it didn't work 
{2015-04-06 15:00:07.155172 +0800 CST it works again} 
at 2015-04-06 15:00:07.155172 +0800 CST, it works again 

Дело спутать меня при каких условиях ДРМ будет неявно называть Интерфейс MyError.Error().

Насколько я понимаю, первый и второй fmt.Println() должны иметь одинаковый тип переменной: MyError. Но очевидно, что первый вызов включал неявный вызов Error() типа MyError, а второй - нет.

Какой механизм сделал это различие?

Спасибо, что заглянули в вопрос этого новичка!

ответ

1

Ваш код связывает реализацию Error() с указателем * MyError.

В вашем коде вы передаете тип (его копию, чтобы быть точным), а не указатель.

Если вы изменяете

err1 := MyError{time.Now(), "it works again"} 

в

err1 := &MyError{time.Now(), "it works again"} 

он будет работать, как вы ожидаете.

+0

Спасибо! Я тестировал и да. –

0

fmt.Println использует отражение, чтобы сначала проверить тип переменной, и если тип реализует интерфейс Stringer, он вызывает метод String. Во-вторых, если тип реализует интерфейс Error, он вызывает метод Error.

+0

Спасибо за объяснение! Еще один вопрос, для типа структуры, GoLang имеет реализацию по умолчанию для stringer, если мы реализуем интерфейс ошибки, запутает ли он fmt.Println, задаваясь вопросом, какой интерфейс использовать? –

+1

На самом деле все наоборот. 'Error() string' используется раньше (в предпочтении)' String() error'. –

+0

@DaveC Что смешно? как если бы вы определяли как 'Error() string', было бы бесполезно определять' String() string', atleast not на указателе на ваш тип struct ... –

Смежные вопросы