// parseConfig returns a parsed configuration for an Azure cloudprovider config filefuncparseConfig(configReaderio.Reader)(*Config,error){varconfigConfigifconfigReader==nil{return&config,nil}configContents,err:=ioutil.ReadAll(configReader)iferr!=nil{returnnil,err}err=yaml.Unmarshal(configContents,&config)iferr!=nil{returnnil,err}// The resource group name may be in different cases from different Azure APIs, hence it is converted to lower here.// See more context at https://github.com/kubernetes/kubernetes/issues/71994.config.ResourceGroup=strings.ToLower(config.ResourceGroup)return&config,nil}
fmt.Errorf(“failed to start kubernetes.io/kube-apiserver-client-kubelet certificate controller: %v”, err)
实现Error()方法的自定义类型
客户段需要检测并处理该错误时使用该方式
见下文自定义error
Error wrapping
Go 1.13支持的特性
errors.New
原则:
不要在客户端判断error中的包含字符串信息。
Bad
Good
```go
// package foo
func Open() error {
return errors.New(“could not open”)
}
// package bar
func use() {
if err := foo.Open(); err != nil {
if err.Error() == “could not open” {
// handle
} else {
panic(“unknown error”)
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</td><td>```go//packagefoovarErrCouldNotOpen=errors.New("could not open")funcOpen()error{returnErrCouldNotOpen}//packagebariferr:=foo.Open();err!=nil{iferrors.Is(err,foo.ErrCouldNotOpen){//handle}else{panic("unknown error")}}
// file: k8s.io/kubernetes/pkg/volume/util/nestedpendingoperations/nestedpendingoperations.go// NewAlreadyExistsError returns a new instance of AlreadyExists error.funcNewAlreadyExistsError(operationNamestring)error{returnalreadyExistsError{operationName}}// IsAlreadyExists returns true if an error returned from// NestedPendingOperations indicates a new operation can not be started because// an operation with the same operation name is already executing.funcIsAlreadyExists(errerror)bool{switcherr.(type){casealreadyExistsError:returntruedefault:returnfalse}}typealreadyExistsErrorstruct{operationNamestring}var_error=alreadyExistsError{}func(erralreadyExistsError)Error()string{returnfmt.Sprintf("Failed to create operation with name %q. An operation with that name is already executing.",err.operationName)}
还可以延伸出更复杂一些的树形error体系:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// package nettypeErrorinterface{errorTimeout()bool// Is the error a timeout?Temporary()bool// Is the error temporary?}typeUnknownNetworkErrorstringfunc(eUnknownNetworkError)Error()stringfunc(eUnknownNetworkError)Temporary()boolfunc(eUnknownNetworkError)Timeout()bool
Error Wrapping
error类型仅包含一个字符串类型的信息,如果函数的调用栈信息为A -> B -> C,如果函数C返回err,在函数A处打印err信息,那么很难判断出err的真正出错位置,不利于快速定位问题。我们期望的效果是在函数A出打印err,能够精确的找到err的源头。