Maison >développement back-end >Golang >Quel est le type d'erreur en langage Go ?

Quel est le type d'erreur en langage Go ?

青灯夜游
青灯夜游original
2023-01-12 11:09:523112parcourir

En langage Go, l'erreur est un type d'interface. Le type d'interface d'erreur est un mode standard pour le traitement des erreurs. Si la fonction renvoie une erreur, la liste des types de valeurs de retour doit contenir une erreur. Le processus de traitement des erreurs est similaire au code d'erreur en langage C et peut être renvoyé couche par couche jusqu'à ce que le code d'erreur soit renvoyé. il est traité. Le type d'interface d'erreur est défini comme une chaîne Error() contenant une seule méthode ; tous les types qui implémentent cette interface peuvent être utilisés comme type d'erreur.

Quel est le type d'erreur en langage Go ?

L'environnement d'exploitation de ce tutoriel : système Windows 7, GO version 1.18, ordinateur Dell G3.

Les erreurs Go font référence à des mécanismes de rétroaction humaine ou automatique provoqués par des situations incompatibles avec le processus de conception lors de l'exécution du programme. Certaines erreurs sont délibérément conçues et une gestion des erreurs est ajoutée, ou un retour est donné à l'utilisateur pour qu'il attende le traitement. Par exemple, si le diviseur est vérifié comme étant 0, une erreur sera signalée afin que l'utilisateur puisse reconnaître le problème. sa propre entrée. Un autre exemple consiste à explorer les informations de page spécifiées. Le code a rencontré une déconnexion du réseau ; d'autres erreurs étaient des BUG causés par une mauvaise programmation, tels que des indices d'accès au tableau hors des limites, des opérations de pointeur nul conduisant à des plantages, etc. Une gestion des erreurs bien conçue pour diverses situations est l'un des signes d'un code mature, et elle nécessite également une expérience accumulée ou une conception minutieuse.

Type d'erreur de langage Go

L'erreur Go est représentée par error, qui est un type d'interface et est généralement déclarée avec la valeur de retour.

La gestion des erreurs est une partie importante de chaque langage de programmation. Habituellement, il existe deux types d'exceptions et d'erreurs rencontrées lors du développement, et le langage Go ne fait pas exception.

En langage C, les erreurs sont exprimées en renvoyant des informations telles que -1 ou NULL, mais pour les utilisateurs, s'ils ne vérifient pas la documentation de l'API correspondante, ils ne sauront pas ce que signifie la valeur de retour, comme renvoyer 0 Succès ou échec ?

Compte tenu de cette situation, le type d'interface d'erreur est introduit dans le langage Go comme mode standard pour la gestion des erreurs. Si la fonction renvoie une erreur, la liste des types de valeurs de retour doit contenir une erreur. Le processus de traitement des erreurs est similaire au code d'erreur en langage C et peut être renvoyé couche par couche jusqu'à ce qu'il soit traité.

Le type d'interface d'erreur est défini comme une chaîne Error() contenant une seule méthode. Tous les types qui implémentent cette interface peuvent être traités comme un type d'erreur. La méthode Error() donne une description de l'erreur. Cela signifie que tous les types de données peuvent être équipés de types d'erreur.

//The error built-in interface type is the conventional interface for representing an error condition, with the nil value representing no error. 
type error interface {
    Error() string
}
//DNSError represents a DNS lookup error. 
type DNSError struct {
    Err         string // description of the error
    Name        string // name looked for
    Server      string // server used
    IsTimeout   bool   // if true, timed out; not all timeouts set this
    IsTemporary bool   // if true, error is temporary; not all errors set this; added in Go 1.6
}

func (e *DNSError) Error() string

func (e *DNSError) Temporary() bool
//Temporary reports whether the DNS error is known to be temporary. This is not always known; a DNS lookup may fail due to a temporary error and return a DNSError for which Temporary returns false. 

func (e *DNSError) Timeout() bool
//Timeout reports whether the DNS lookup is known to have timed out. This is not always known; a DNS lookup may fail due to a timeout and return a DNSError for which Timeout returns false.

Regardez spécifiquement *DNSError pour comprendre la définition d'un type d'erreur. *DNSError contient 5 structures de champs. Err décrit le texte de l'erreur, Name est le nom de domaine de la requête, utilisé par le serveur Server, et IsTimeout et IsTemporary sont deux quantités booléennes indiquant la cause de l'erreur. Utilisez les exemples suivants pour comprendre cela en détail.

func main() {
    name := "www.ilydsssss.com"
    addr, err := net.LookupHost(name)
    if errS, ok := err.(*net.DNSError); ok {
        fmt.Printf("%+v\n", *errS)
        fmt.Println(err)
    } else {
        fmt.Println(name, addr)
    }  
}
/* result for
------www.ilydsssss.com------------
{Err:no such host Name:www.ilydsssss.com Server: IsTimeout:false IsTemporary:false}
lookup www.ilydsssss.com: no such host

------------ www.iloveyou.com------------
{Err:getaddrinfow: This is usually a temporary error during hostname resolution and means that the local server did not receive a response from an authoritative server. Name:www.iloveyou.com Server: IsTimeout:false IsTemporary:false}
lookup www.iloveyou.com: getaddrinfow: This is usually a temporary error during hostname resolution and means that the local server did not receive a response from an authoritative server.
传说中的发送DNS,没有返回的结果,原因你懂的, 这个是什么站点,noidea

----------- www.baidu.com ------------
www.baidu.com [180.97.33.108 180.97.33.107]

Dans le cas d'utilisation ci-dessus, si la requête échoue (c'est-à-dire que le pointeur n'est pas nul), une assertion de type est effectuée S'il s'agit d'un pointeur *net.DNSError, le champ de structure est imprimé et une erreur est générée. ; sinon, le nom de domaine et l'adresse sont imprimés. On constate que parmi les deux types d'erreurs définis, la requête ci-dessus n'en a renvoyé aucune, mais il s'agissait bien d'une erreur.

En même temps, vous pouvez également deviner que la définition de la chaîne func (e *DNSError) Error() est return "look " + e.Name + e.Err.

création d'erreur

Le retour d'erreur interne de Go est défini de cette manière. Comment définir un nouveau type d'erreur.

  • Définissez la structure et implémentez l'interface d'erreur

Créez une nouvelle structure, modélisez le DNSError ci-dessus pour créer une structure qui doit enregistrer les erreurs et implémentez l'interface d'erreur en même temps, cela peut être atteint.

  • fonction error.New()

package errors
// New returns an error that formats as the given text.
func New(text string) error {
    return &errorString{text}
}
// errorString is a trivial implementation of error.
type errorString struct {
    s string
}
func (e *errorString) Error() string {
    return e.s
}

errorString est un type de structure qui contient uniquement une chaîne et implémente l'interface d'erreur. La fonction New() est simplement initialisée avec une chaîne décrivant l'erreur errorString et renvoie. l'adresse de la structure, qui permet d'appeler directement à tout moment un type d'erreur simple sans avoir à créer de structure et à implémenter l'interface. Si nécessaire, utiliser la méthode 1.

  • Utilisez fmt.Errorf() pour renvoyer l'interface d'erreur

fmt.Errorf() signature de fonction : func Errorf(format string, a ...interface{}), qui utilise un caractère formaté String, en utilisant la méthode ci-dessus, renvoie une signature. Vous souvenez-vous encore de cette chaîne func Sprintf(format string, a ...interface{}), l'implémentation de fmt.Errorf() ne renvoie qu'une erreur.New(fmt.Sprintf(format string, a ...interface{}))

Gestion des erreurs

当写一个库时,如果发生一个错误,一种方式就是按照上述所说,抛出一个错误,由上层或用户去决断如何处理,是退出还是提示修改;另一种方式就是抛出 panic 来终止程序,除非遇到特别严重的错误,什么叫严重呢?就是程序已经没有执行的必要了,莫不如抛出错误,直接退出。有两种情况可以考虑使用 panic: 1. 发生了一个不能恢复的错误,此时程序不能继续运行。2. 存在一个编程上的错误。

当程序由 panic 引发终止时,可以使用 recover 重新获取该程序控制权。panic 和 recover 与其他语言中的 try-catch-finally 语句类似,只不过一般我们很少使用 panic 和 recover。

内建函数 panic 的签名为:func panic(interface{}),此处接口为空接口,也可以理解为任意数据类型都可以输入,输入什么,则提示什么。

func div(x, y int) float64 {
    defer fmt.Println("DIV ......")
    if y == 0 {
        panic(fmt.Sprintf("%d / %d, 除数为零, 无法计算", x, y))
    }
    return float64(x) / float64(y)
}
fmt.Println(div(3, 0))
/* result
panic: 3 / 0, 除数为零

goroutine 1 [running]:
main.div(0x3, 0x0, 0x2)
        error.go:10 +0x148
main.main()
        error.go:25 +0x15a
exit status 2
*/

从上述例子可以看到,当函数发生 panic 时,它会终止运行,在执行完所有的延迟函数后,程序控制返回到该函数的调用方。这样的过程会一直持续下去,直到当前协程的所有函数都返回退出,然后程序会打印出 panic 信息,接着打印出堆栈跟踪,最后程序终止。

recover 是一个内建函数,用于重新获得 panic 协程的控制。recover 函数的标签如下所示:func recover() interface{}。需要注意的是:只有在延迟函数的内部,调用 recover 才有用。在延迟函数内调用 recover,可以取到 panic 的错误信息,并且停止 panic 续发事件,程序运行恢复正常。如果在延迟函数的外部调用 recover,就不能停止 panic 续发事件。

例如:

import (
    "runtime/debug"
)
func recoverFdiv() {
    if r := recover(); r != nil {
        fmt.Println("来自 DIV 的恢复, 除数为零,下面是出错log记录")
        debug.PrintStack()
    }
}

func div(x, y int) float64 {
    defer recoverFdiv()
    if y == 0 {
        panic(fmt.Sprintf("%d / %d, 除数为零, 无法计算", x, y))
    }
    return float64(x) / float64(y)
}
fmt.Println(div(3, 0))

/* result
来自 DIV 的恢复, 除数为零,下面是出错log记录
goroutine 1 [running]:
runtime/debug.Stack(0xc000072008, 0xc00006fd68, 0x1)
        runtime/debug/stack.go:24 +0xae
runtime/debug.PrintStack()
        runtime/debug/stack.go:16 +0x29
main.recoverFdiv()
        D:/ZHY-L/OneDrive/文档/开发/goblog/myerror.go:12 +0x89
panic(0x4b9620, 0xc000030040)
        runtime/panic.go:513 +0x1c7
main.div(0x3, 0x0, 0x0)
        error.go:19 +0x186
main.main()
        error.go:34 +0x15a
0
*/

如上所示,调用延迟函数 recoverFdiv(),它使用了 recover() 来停止 panic 续发事件,主函数还是继续执行了。同时,利用debug.PrintStack() 打印了 panic 记录,这样在保证程序继续执行的同时,也留下了调试宝贵的记录。

同理,Go 内置的运行时错误(如数组越界)也会导致 panic。这等价于调用了内置函数 panic,其参数由接口类型 runtime.Error 给出。runtime.Error 接口的定义如下:

type Error interface {  
    error
    // RuntimeError is a no-op function but
    // serves to distinguish types that are run time
    // errors from ordinary errors: a type is a
    // run time error if it has a RuntimeError method.
    RuntimeError()
}

【相关推荐:Go视频教程编程教学

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn