W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
原文鏈接:https://gopl-zh.github.io/ch7/ch7-11.html
思考在os包中文件操作返回的錯(cuò)誤集合。I/O可以因?yàn)槿魏螖?shù)量的原因失敗,但是有三種經(jīng)常的錯(cuò)誤必須進(jìn)行不同的處理:文件已經(jīng)存在(對(duì)于創(chuàng)建操作),找不到文件(對(duì)于讀取操作),和權(quán)限拒絕。os包中提供了三個(gè)幫助函數(shù)來對(duì)給定的錯(cuò)誤值表示的失敗進(jìn)行分類:
package os
func IsExist(err error) bool
func IsNotExist(err error) bool
func IsPermission(err error) bool
對(duì)這些判斷的一個(gè)缺乏經(jīng)驗(yàn)的實(shí)現(xiàn)可能會(huì)去檢查錯(cuò)誤消息是否包含了特定的子字符串,
func IsNotExist(err error) bool {
// NOTE: not robust!
return strings.Contains(err.Error(), "file does not exist")
}
但是處理I/O錯(cuò)誤的邏輯可能一個(gè)和另一個(gè)平臺(tái)非常的不同,所以這種方案并不健壯,并且對(duì)相同的失敗可能會(huì)報(bào)出各種不同的錯(cuò)誤消息。在測(cè)試的過程中,通過檢查錯(cuò)誤消息的子字符串來保證特定的函數(shù)以期望的方式失敗是非常有用的,但對(duì)于線上的代碼是不夠的。
一個(gè)更可靠的方式是使用一個(gè)專門的類型來描述結(jié)構(gòu)化的錯(cuò)誤。os包中定義了一個(gè)PathError類型來描述在文件路徑操作中涉及到的失敗,像Open或者Delete操作;并且定義了一個(gè)叫LinkError的變體來描述涉及到兩個(gè)文件路徑的操作,像Symlink和Rename。這下面是os.PathError:
package os
// PathError records an error and the operation and file path that caused it.
type PathError struct {
Op string
Path string
Err error
}
func (e *PathError) Error() string {
return e.Op + " " + e.Path + ": " + e.Err.Error()
}
大多數(shù)調(diào)用方都不知道PathError并且通過調(diào)用錯(cuò)誤本身的Error方法來統(tǒng)一處理所有的錯(cuò)誤。盡管PathError的Error方法簡(jiǎn)單地把這些字段連接起來生成錯(cuò)誤消息,PathError的結(jié)構(gòu)保護(hù)了內(nèi)部的錯(cuò)誤組件。調(diào)用方需要使用類型斷言來檢測(cè)錯(cuò)誤的具體類型以便將一種失敗和另一種區(qū)分開;具體的類型可以比字符串提供更多的細(xì)節(jié)。
_, err := os.Open("/no/such/file")
fmt.Println(err) // "open /no/such/file: No such file or directory"
fmt.Printf("%#v\n", err)
// Output:
// &os.PathError{Op:"open", Path:"/no/such/file", Err:0x2}
這就是三個(gè)幫助函數(shù)是怎么工作的。例如下面展示的IsNotExist,它會(huì)報(bào)出是否一個(gè)錯(cuò)誤和syscall.ENOENT(§7.8)或者和有名的錯(cuò)誤os.ErrNotExist相等(可以在§5.4.2中找到io.EOF);或者是一個(gè)*PathError
,它內(nèi)部的錯(cuò)誤是syscall.ENOENT和os.ErrNotExist其中之一。
import (
"errors"
"syscall"
)
var ErrNotExist = errors.New("file does not exist")
// IsNotExist returns a boolean indicating whether the error is known to
// report that a file or directory does not exist. It is satisfied by
// ErrNotExist as well as some syscall errors.
func IsNotExist(err error) bool {
if pe, ok := err.(*PathError); ok {
err = pe.Err
}
return err == syscall.ENOENT || err == ErrNotExist
}
下面這里是它的實(shí)際使用:
_, err := os.Open("/no/such/file")
fmt.Println(os.IsNotExist(err)) // "true"
如果錯(cuò)誤消息結(jié)合成一個(gè)更大的字符串,當(dāng)然PathError的結(jié)構(gòu)就不再為人所知,例如通過一個(gè)對(duì)fmt.Errorf函數(shù)的調(diào)用。區(qū)別錯(cuò)誤通常必須在失敗操作后,錯(cuò)誤傳回調(diào)用者前進(jìn)行。
![]() | ![]() |
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: