国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

如何處理Golang中的錯(cuò)誤

與其他主流編程語(yǔ)言(例如 JavaScript(使用語(yǔ)句try… catch)或 Python(及其try… except塊))中的傳統(tǒng)方法不同,Go 中處理錯(cuò)誤需要不同的方法。為什么?因?yàn)樗腻e(cuò)誤處理功能經(jīng)常被誤用。

在這篇博文中,我們將了解可用于處理 Go 應(yīng)用程序中的錯(cuò)誤的最佳實(shí)踐。消化本文所需的只是對(duì)Go(https://golang.org/doc/)工作原理的基本了解- 如果您在某些時(shí)候感到陷入困境,可以花一些時(shí)間研究不熟悉的概念。

空白標(biāo)識(shí)符

空白標(biāo)識(shí)符(https://golang.org/doc/effective_go.html#blank)是匿名占位符。它可以像聲明中的任何其他標(biāo)識(shí)符一樣使用,但它不引入綁定??瞻讟?biāo)識(shí)符提供了一種忽略賦值中的左手值并避免有關(guān)程序中未使用的導(dǎo)入和變量的編譯器錯(cuò)誤的方法。將錯(cuò)誤分配給空白標(biāo)識(shí)符而不是正確處理它們的做法是不安全的,因?yàn)檫@意味著您決定顯式忽略已定義函數(shù)的值。

result, _ := iterate(x,y)

if value > 0 {
  // 確保在結(jié)果之前檢查錯(cuò)誤。
}

您這樣做的原因可能是您不希望函數(shù)出現(xiàn)錯(cuò)誤(或可能發(fā)生的任何錯(cuò)誤),但這可能會(huì)在您的程序中產(chǎn)生級(jí)聯(lián)效應(yīng)。最好的辦法是盡可能處理錯(cuò)誤。

通過(guò)多個(gè)返回值處理錯(cuò)誤

處理錯(cuò)誤的一種方法是利用 Go 中的函數(shù)支持多個(gè)返回值這一事實(shí)。因此,您可以將錯(cuò)誤變量與您定義的函數(shù)的結(jié)果一起傳遞:

func iterate(x, y int) (int, error) {

}

error在上面的代碼示例中,如果我們認(rèn)為函數(shù)有可能失敗,則必須返回預(yù)定義變量。error是 Go 包中聲明的接口類型built-in,其零值為nil。

type error interface {
   Error() string
 }

通常,返回錯(cuò)誤意味著有問(wèn)題,返回nil意味著沒(méi)有錯(cuò)誤:

result, err := iterate(x, y)
 if err != nil {
  // 適當(dāng)處理錯(cuò)誤
 } else {
  // 你可以走了
 }

因此,每當(dāng)函數(shù)iterate被調(diào)用并且err不等于 時(shí)nil,返回的錯(cuò)誤都應(yīng)該得到適當(dāng)?shù)奶幚怼粋€(gè)選項(xiàng)可以是創(chuàng)建重試或清理機(jī)制的實(shí)例。以這種方式處理錯(cuò)誤的唯一缺點(diǎn)是 Go 編譯器沒(méi)有強(qiáng)制執(zhí)行,您必須決定您創(chuàng)建的函數(shù)如何返回錯(cuò)誤。您可以定義一個(gè)錯(cuò)誤結(jié)構(gòu)并將其放置在返回值的位置。一種方法是使用內(nèi)置結(jié)構(gòu)體(您也可以在Go 的源代碼(https://golang.org/src/errors/errors.go)errorString中找到此代碼):

package errors

 func New(text string) error {
     return &errorString {
         text
     }
 }

 type errorString struct {
     s string
 }

 func(e * errorString) Error() string {
     return e.s
 }

在上面的代碼示例中,嵌入了該方法返回的errorStringa 。要?jiǎng)?chuàng)建自定義錯(cuò)誤,您必須定義錯(cuò)誤結(jié)構(gòu)并使用方法集將函數(shù)與結(jié)構(gòu)關(guān)聯(lián)起來(lái):stringError

// 定義一個(gè)錯(cuò)誤結(jié)構(gòu)體
type CustomError struct {
  msg string
}
// 創(chuàng)建一個(gè)函數(shù) Error() 字符串并將其關(guān)聯(lián)到結(jié)構(gòu)體。
func(error * CustomError) Error() string {
  return error.msg
}
// 然后使用 MyError 結(jié)構(gòu)創(chuàng)建一個(gè)錯(cuò)誤對(duì)象。
func CustomErrorInstance() error {
  return &CustomError {
      "File type not supported"
  }
}

然后可以重組新創(chuàng)建的自定義錯(cuò)誤以使用內(nèi)置error結(jié)構(gòu):

import "errors"
func CustomeErrorInstance() error {
    return errors.New("File type not supported")
}

內(nèi)置error結(jié)構(gòu)的一個(gè)限制是它不帶有堆棧跟蹤。這使得定位錯(cuò)誤發(fā)生的位置變得非常困難。該錯(cuò)誤在打印出來(lái)之前可能會(huì)經(jīng)過(guò)多個(gè)函數(shù)。為了解決這個(gè)問(wèn)題,您可以安裝pkg/errors提供基本錯(cuò)誤處理原語(yǔ)的包,例如堆棧跟蹤記錄、錯(cuò)誤包裝、展開(kāi)和格式化。要安裝此軟件包,請(qǐng)?jiān)诮K端中運(yùn)行以下命令:

go get github.com/pkg/errors

當(dāng)您需要添加堆棧跟蹤或任何其他信息以便更輕松地調(diào)試錯(cuò)誤時(shí),請(qǐng)使用 或 函數(shù)New來(lái)Errorf提供記錄堆棧跟蹤的錯(cuò)誤。Errorf實(shí)現(xiàn)fmt.Formatter允許您使用fmt包 runes(%s、等)格式化錯(cuò)誤的接口%v:%+v

import(
  "github.com/pkg/errors"
  "fmt"
)
func X() error {
  return errors.Errorf("Could not write to file")
}

func customError() {
  return X()
}

func main() {
  fmt.Printf("Error: %+v", customError())
}

要打印堆棧跟蹤而不是普通的錯(cuò)誤消息,您必須在格式模式中使用%+v 而不是%v,堆棧跟蹤將類似于下面的代碼示例:

Error: Could not write to file
main.X
 /Users/raphaelugwu/Go/src/golangProject/error_handling.go:7
main.customError
 /Users/raphaelugwu/Go/src/golangProject/error_handling.go:15
main.main
 /Users/raphaelugwu/Go/src/golangProject/error_handling.go:19
runtime.main
 /usr/local/opt/go/libexec/src/runtime/proc.go:192
runtime.goexit
 /usr/local/opt/go/libexec/src/runtime/asm_amd64.s:2471

推遲、恐慌和恢復(fù)

盡管 Go 沒(méi)有例外,但它有一種類似的機(jī)制,稱為“延遲、恐慌和恢復(fù)”。Go 的理念是,添加異常(例如try/catch/finallyJavaScript 中的語(yǔ)句)會(huì)導(dǎo)致代碼復(fù)雜,并鼓勵(lì)程序員將太多基本錯(cuò)誤(例如無(wú)法打開(kāi)文件)標(biāo)記為異常。你不應(yīng)該defer/panic/recover像你想的那樣使用throw/catch/finally;僅在意外的、不可恢復(fù)的故障的情況下。

Defer是一種將函數(shù)調(diào)用放入堆棧的語(yǔ)言機(jī)制。當(dāng)主機(jī)函數(shù)完成時(shí),無(wú)論是否調(diào)用恐慌,每個(gè)延遲函數(shù)都會(huì)以相反的順序執(zhí)行。defer機(jī)制對(duì)于清理資源非常有用:

package main

import (
        "fmt"
)

func A() {
        defer fmt.Println("Keep calm!")
        B()
}
func B() {
        defer fmt.Println("Else...")
        C()
}
func C() {
        defer fmt.Println("Turn on the air conditioner...")
        D()
}
func D() {
        defer fmt.Println("If it's more than 30 degrees...")
}
func main() {
        A()
}

這將編譯為:

If it's more than 30 degrees...
Turn on the air conditioner...
Else...
Keep calm!

Panic是一個(gè)停止正常執(zhí)行流程的內(nèi)置函數(shù)。當(dāng)您調(diào)用panic代碼時(shí),這意味著您已經(jīng)確定調(diào)用者無(wú)法解決問(wèn)題。因此,panic僅應(yīng)在極少數(shù)情況下使用,在這種情況下,您的代碼或集成您的代碼的任何人在此時(shí)繼續(xù)不安全。下面是描述工作原理的代碼示例panic:

package mainimport (
package main

import (
        "errors"
        "fmt"
)

func A() {
        defer fmt.Println("Then we can't save the earth!")
        B()
}
func B() {
        defer fmt.Println("And if it keeps getting hotter...")
        C()
}
func C() {
        defer fmt.Println("Turn on the air conditioner...")
        Break()
}
func Break() {
        defer fmt.Println("If it's more than 30 degrees...")
        panic(errors.New("Global Warming!!!"))

}
func main() {
        A()
}

上面的示例將編譯為:

If it's more than 30 degrees...
Turn on the air conditioner...
And if it keeps getting hotter...
Then we can't save the earth!
panic: Global Warming!!!

goroutine 1 [running]:
main.Break()
        /tmp/sandbox186240156/prog.go:22 +0xe0
main.C()
        /tmp/sandbox186240156/prog.go:18 +0xa0
main.B()
        /tmp/sandbox186240156/prog.go:14 +0xa0
main.A()
        /tmp/sandbox186240156/prog.go:10 +0xa0
main.main()
        /tmp/sandbox186240156/prog.go:26 +0x20

Program exited: status 2.

如上所示,當(dāng)panic使用但未處理時(shí),執(zhí)行流程停止,所有延遲函數(shù)按相反順序執(zhí)行,并打印堆棧跟蹤。

您可以使用recover內(nèi)置函數(shù)來(lái)處理panic和返回從緊急調(diào)用傳遞的值。recover必須始終在函數(shù)中調(diào)用,defer否則它將返回nil:

package main

import (
        "errors"
        "fmt"
)

func A() {
        defer fmt.Println("Then we can't save the earth!")
        defer func() {
                if x := recover(); x != nil {
                        fmt.Printf("Panic: %+v\n", x)
                }
        }()
        B()
}
func B() {
        defer fmt.Println("And if it keeps getting hotter...")
        C()
}
func C() {
        defer fmt.Println("Turn on the air conditioner...")
        Break()
}
func Break() {
        defer fmt.Println("If it's more than 30 degrees...")
        panic(errors.New("Global Warming!!!"))

}
func main() {
        A()
}

從上面的代碼示例中可以看出,recover這可以防止整個(gè)執(zhí)行流程停止,因?yàn)槲覀兎湃胍粋€(gè)panic函數(shù),編譯器將返回:

If it's more than 30 degrees...
Turn on the air conditioner...
And if it keeps getting hotter...
Panic: Global Warming!!!
Then we can't save the earth!Program exited.

要將錯(cuò)誤報(bào)告為返回值,您必須在調(diào)用recover函數(shù)的同一goroutine中調(diào)用該函數(shù)panic,從函數(shù)中檢索錯(cuò)誤結(jié)構(gòu)recover,并將其傳遞給變量:

package main

import (
        "errors"
        "fmt"
)

func saveEarth() (err error) {

        defer func() {
                if r := recover(); r != nil {
                        err = r.(error)
                }
        }()
        TooLate()
        return
}
func TooLate() {
        A()
        panic(errors.New("Then there's nothing we can do"))
}

func A() {
        defer fmt.Println("If it's more than 100 degrees...")
}
func main() {
        err := saveEarth()
        fmt.Println(err)
}

每個(gè)延遲函數(shù)都將在函數(shù)調(diào)用之后但 return 語(yǔ)句之前執(zhí)行。因此,您可以在執(zhí)行 return 語(yǔ)句之前設(shè)置返回變量。上面的代碼示例將編譯為:

If it's more than 100 degrees...
Then there's nothing we can doProgram exited.

錯(cuò)誤換行

以前,Go 中的錯(cuò)誤包裝只能通過(guò)使用pkg/errors. 然而,Go 的最新版本 -版本 1.13提供了對(duì)錯(cuò)誤包裝的支持。根據(jù)發(fā)行說(shuō)明:

一個(gè)錯(cuò)誤可以通過(guò)提供返回 的方法來(lái)e包裝另一個(gè)錯(cuò)誤。和都可供程序使用,允許提供額外的上下文或重新解釋它,同時(shí)仍然允許程序基于 做出決策。wUnwrapweweww

為了創(chuàng)建包裝錯(cuò)誤,fmt.Errorf現(xiàn)在有一個(gè)%w動(dòng)詞,并且為了檢查和展開(kāi)錯(cuò)誤,已在包中添加了幾個(gè)函數(shù)error:

errors.Unwrap:該函數(shù)主要檢查并暴露程序中的潛在錯(cuò)誤。Unwrap它返回調(diào)用上的方法的結(jié)果Err。如果 Err 的類型包含Unwrap返回錯(cuò)誤的方法。否則,Unwrap返回nil。

package errors

type Wrapper interface{
  Unwrap() error
}

下面是該方法的示例實(shí)現(xiàn)Unwrap:

func(e*PathError)Unwrap()error{
  return e.Err
}

errors.Is:使用此功能,您可以將錯(cuò)誤值與哨兵值進(jìn)行比較。該函數(shù)與我們通常的錯(cuò)誤檢查的不同之處在于,它不是將哨兵值與一個(gè)錯(cuò)誤進(jìn)行比較,而是將其與錯(cuò)誤鏈中的每個(gè)錯(cuò)誤進(jìn)行比較。它還實(shí)現(xiàn)了一個(gè)Is錯(cuò)誤方法,以便錯(cuò)誤可以將自己作為哨兵發(fā)布,即使它不是哨兵值。

func Is(err, target error) bool

在上面的基本實(shí)現(xiàn)中,Is檢查并報(bào)告其鏈中的err任何一個(gè)是否errors等于目標(biāo)(哨兵值)。

errors.As:該函數(shù)提供了一種轉(zhuǎn)換為特定錯(cuò)誤類型的方法。它查找錯(cuò)誤鏈中與哨兵值匹配的第一個(gè)錯(cuò)誤,如果找到,則將哨兵值設(shè)置為該錯(cuò)誤值并返回true:

package main

import (
        "errors"
        "fmt"
        "os"
)

func main() {
        if _, err := os.Open("non-existing"); err != nil {
                var pathError *os.PathError
                if errors.As(err, &pathError) {
                        fmt.Println("Failed at path:", pathError.Path)
                } else {
                        fmt.Println(err)
                }
        }

}

你可以在Go的源代碼中找到這段代碼。(https://golang.org/pkg/errors/#As)

編譯結(jié)果:

Failed at path: non-existing
Program exited.

如果錯(cuò)誤的具體值可分配給哨兵值指向的值,則錯(cuò)誤與哨兵值匹配。As如果哨兵值不是指向?qū)崿F(xiàn)錯(cuò)誤的類型或任何接口類型的非零指針,則會(huì)出現(xiàn)恐慌。如果是As則返回 false 。errnil

概括

Go 社區(qū)最近在支持各種編程概念并引入更簡(jiǎn)潔、更簡(jiǎn)單的錯(cuò)誤處理方法方面取得了令人印象深刻的進(jìn)步。您對(duì)如何處理 Go 程序中可能出現(xiàn)的錯(cuò)誤有任何想法嗎?請(qǐng)?jiān)谙旅娴脑u(píng)論中告訴我。

資源:

關(guān)于類型斷言的 Go 編程語(yǔ)言規(guī)范(https://golang.org/ref/spec#Type_assertions)

Go 1.13 發(fā)行說(shuō)明(https://golang.org/doc/go1.13)


文章來(lái)源地址http://www.zghlxwxcb.cn/article/346.html

到此這篇關(guān)于如何處理Golang中的錯(cuò)誤的文章就介紹到這了,更多相關(guān)內(nèi)容可以在右上角搜索或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

原文地址:http://www.zghlxwxcb.cn/article/346.html

如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)聯(lián)系站長(zhǎng)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • golang的錯(cuò)誤處理

    在軟件開(kāi)發(fā)中,錯(cuò)誤處理是一個(gè)非常重要的方面。它涉及到識(shí)別、捕獲和處理在程序執(zhí)行期間可能發(fā)生的錯(cuò)誤。在Golang中,錯(cuò)誤處理是一個(gè)值得關(guān)注的主題,因?yàn)樗鼮殚_(kāi)發(fā)人員提供了一種優(yōu)雅且高效的方式來(lái)處理錯(cuò)誤情況。本文將深入探討Golang的錯(cuò)誤處理機(jī)制,并為您提供一

    2024年02月08日
    瀏覽(42)
  • os.signal golang中的信號(hào)處理

    在程序進(jìn)行重啟等操作時(shí),我們需要讓程序完成一些重要的任務(wù)之后,優(yōu)雅地退出,Golang為我們提供了signal包,實(shí)現(xiàn)信號(hào)處理機(jī)制,允許Go 程序與傳入的信號(hào)進(jìn)行交互。 Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)中signal包的核心功能主要包含以下幾個(gè)方面: 1. signal處理的全局狀態(tài)管理 通過(guò)handlers結(jié)構(gòu)體跟

    2024年02月15日
    瀏覽(30)
  • 100天精通Golang(基礎(chǔ)入門篇)——第23天:錯(cuò)誤處理的藝術(shù): Go語(yǔ)言實(shí)戰(zhàn)指南

    100天精通Golang(基礎(chǔ)入門篇)——第23天:錯(cuò)誤處理的藝術(shù): Go語(yǔ)言實(shí)戰(zhàn)指南

    ???? 博主貓頭虎???? 帶您進(jìn)入 Golang 語(yǔ)言的新世界???? ?? 博客首頁(yè) ——????貓頭虎的博客?? ?? 《面試題大全專欄》 ?? 文章圖文并茂??生動(dòng)形象??簡(jiǎn)單易學(xué)!歡迎大家來(lái)踩踩~?? ?? 《IDEA開(kāi)發(fā)秘籍專欄》 ?? 學(xué)會(huì)IDEA常用操作,工作效率翻倍~?? ?? 《100天精通

    2024年02月07日
    瀏覽(36)
  • Golang中的管道(channel) 、goroutine與channel實(shí)現(xiàn)并發(fā)、單向管道、select多路復(fù)用以及goroutine panic處理

    Golang中的管道(channel) 、goroutine與channel實(shí)現(xiàn)并發(fā)、單向管道、select多路復(fù)用以及goroutine panic處理

    目錄 管道(channel) 無(wú)緩沖管道 有緩沖管道 需要注意 goroutine與channel實(shí)現(xiàn)并發(fā) 單向管道 定義單向管道 將雙向管道轉(zhuǎn)換為單向管道 單向管道作為函數(shù)參數(shù) 單向管道的代碼示例 select多路復(fù)用 案例演示 goroutine panic處理 案例演示 管道(channel)是 Go 語(yǔ)言中實(shí)現(xiàn)并發(fā)的一種方式,

    2024年02月06日
    瀏覽(24)
  • Golang 一個(gè)支持錯(cuò)誤堆棧, 錯(cuò)誤碼, 錯(cuò)誤鏈的工具庫(kù)

    Golang 一個(gè)支持錯(cuò)誤堆棧, 錯(cuò)誤碼, 錯(cuò)誤鏈的工具庫(kù)

    來(lái)騰訊之后主要使用go, 在業(yè)務(wù)開(kāi)發(fā)中需要一個(gè)支持錯(cuò)誤碼對(duì)外返回, 堆棧打印等能力的錯(cuò)誤工具庫(kù), 先開(kāi)始使用 pkg/errors , 但該項(xiàng)目已經(jīng)只讀, 上次更新是幾年前, 而且有一些點(diǎn)比如調(diào)整堆棧深度等沒(méi)有支持, 后續(xù)根據(jù)業(yè)務(wù)的需要抽取了一個(gè)通用庫(kù), 且做了一些優(yōu)化, 詳見(jiàn)下方.

    2024年02月11日
    瀏覽(20)
  • golang導(dǎo)入go-git錯(cuò)誤記錄

    代碼: 導(dǎo)入: 編譯,報(bào)錯(cuò): 解決: 替換引用。 ref: https://github.com/src-d/go-git/issues/914

    2024年01月22日
    瀏覽(26)
  • golang validator v10 自定義驗(yàn)證方法和錯(cuò)誤

    需要在初始化驗(yàn)證器時(shí)使用

    2024年02月09日
    瀏覽(25)
  • golang之json注釋處理

    json 作為現(xiàn)代比較常用的文本格式,本身是不支持注釋的,因?yàn)樗脑O(shè)計(jì)初衷是作為一種輕量級(jí)數(shù)據(jù)交換格式,只需要包含數(shù)據(jù)本身,而不應(yīng)該包含注釋或者其他無(wú)關(guān)的信息。 但是有時(shí)json內(nèi)字段較多,想寫一些注釋說(shuō)明,這些都是編程工具或者編輯器特有的功能,常見(jiàn)的注釋

    2024年02月17日
    瀏覽(19)
  • golang 字符串操作、處理

    1. len()內(nèi)置系統(tǒng)函數(shù),計(jì)算字符串結(jié)果是字符串的字節(jié)長(zhǎng)度,不是字符長(zhǎng)度 2. 計(jì)算帶中文的字符串長(zhǎng)度。 需要將字符串轉(zhuǎn)為 rune類型(int32) 3.為什么字符串帶中文,字符長(zhǎng)度計(jì)算方式不一樣? 因?yàn)間olang默認(rèn)的字符編碼是utf-8,? 字符串的底層是 []byte類型,英文及標(biāo)點(diǎn)符號(hào)都是

    2024年02月14日
    瀏覽(28)
  • Golang每日一練(leetDay0095) 第一個(gè)錯(cuò)誤的版本、完全平方數(shù)

    Golang每日一練(leetDay0095) 第一個(gè)錯(cuò)誤的版本、完全平方數(shù)

    目錄 278. 第一個(gè)錯(cuò)誤的版本 First Bad Version???? 279. 完全平方數(shù) Perfect Squares?????? ?? 每日一練刷題專欄??? Rust每日一練 專欄 Golang每日一練 專欄 Python每日一練 專欄 C/C++每日一練 專欄 Java每日一練 專欄 你是產(chǎn)品經(jīng)理,目前正在帶領(lǐng)一個(gè)團(tuán)隊(duì)開(kāi)發(fā)新的產(chǎn)品。不幸的是,你

    2024年02月09日
    瀏覽(33)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包