Les structures ne peuvent pas être nul, mais c'est de la compilation
Je suis en train de jouer avec aire de Jeux et trouver ce code:
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() error {
return &MyError{
time.Now(),
"it didn't work",
}
}
func main() {
if err := run(); err != nil {
fmt.Println(err)
}
}
Donc ici, je peux voir que *MyError
implémente error
interface. Cependant, si je retire &
dans error
func et retour MyError
au lieu de cela, je reçois erreur de compilation:
prog.go:19: cannot use MyError literal (type MyError) as type error in return argument: MyError does not implement error (Error method has pointer receiver)
. OK je peux comprendre que, si je peux rendre la fonction Error
comme ça et ce sera de compiler et d'exécuter avec succès:
func (e MyError) Error() string {
return fmt.Sprintf("at %v, %s",
e.When, e.What)
}
func run() error {
return MyError{
time.Now(),
"it didn't work",
}
}
Puis-je voir dans main
func qu'il y est de vérifier si err
est nil
donc, si je comprends bien, il est parfaitement possible func error
de retour nil
dans certaines situations. Il est donc possible pour MyError
struct prendre nil
valeurs. Mais alors, si j'essaie de compiler ce:
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() error {
return nil
return MyError{
time.Now(),
"it didn't work",
}
}
func main() {
var err2 MyError = nil
fmt.Println(err2)
if err := run(); err != nil {
fmt.Println(err)
}
}
aller compilateur dit qu': prog.go:27: cannot use nil as type MyError in assignment
[process exited with non-zero status]
Pourquoi dans la partie supérieure de cas, la compilation est réussie, et dans ce cas, la compilation échoue?
Est-il possible pour les structures à nil
(je suppose que non, mais alors pourquoi run
func compile?)
Vous devez vous connecter pour publier un commentaire.
Dans le premier exemple,
*MyError
mise en œuvre de laerror
interface. Comme vous pouvez le voir, c'est un pointeur, et un pointeur peut avoir lesnil
valeur.Mais dans le deuxième exemple, il est
MyError
qui met en œuvre laerror
interface, et ce n'est pas un pointeur, pas plus.C'est l'adresse de
err
ce temps peut êtrenil
, et non la variable elle-même.A titre de comparaison, considérons le
int
type:var i int
. Vous pouvez le vérifieri == 0
par exemple, mais ce serait une erreur pour tester sii == nil
, parce quenil
n'est pas un entier (exactement comme ce n'était pas unMyError
avant). Mais vous pouvez toujours vérifier si l'adresse dei
estnil
:&i == nil
.MODIFIER
Être conscient que cette fonction toujours retour
nil
(l'exécution s'arrête juste après la premièrereturn
):Il compile parce que le prototype de la fonction nous dit qu'il doit retourner un
error
, et en effet,nil
est valideerror
, et est donc uneMyError{}
variable. Mais essayez de changer ce prototype de fonction de celui-ci:Vous verrez que la compilation échoue, parce que
nil
n'est pas unMyError
variable, même si c'est une valeur valide pour leerror
type.run
la touche func. Il retourne MyError mais aussi peut retourner nil.Un néant de l'interface n'est pas la même chose qu'une interface qui contient une valeur nulle.
Dans votre question, vous avez vu qu'une interface (dans votre cas, le groupe builtin interface d'erreur) peut être nul, et tiré une conclusion erronée que tous les types qui peuvent mettre en œuvre l'interface peut aussi être nul.