我想问一下错误处理的最佳实践, 假设我有以下读取文件的函数来解析它, 当找不到文件且解组失败时,可能会返回两种类型的错误
func Parse(source string) (bma.Bma, error) {
file, err := ioutil.ReadFile(source + "bma.yaml")
m := bma.Bma{}
if err != nil {
logs.Error("Not able to read the bma file")
return m, err
}
err = yaml.Unmarshal([]byte(file), &m)
if err != nil {
logs.Error("Not able to unmarshal the bma file ")
return m, err
}
return m, err
}
现在,如果我调用此函数并且出现错误,我也打印了此错误,则该程序是CLI程序,因此我认为如果出现问题,可以吗,或者有更好的方法,将会打印太多错误?
bma ,err := Parse("path")
if err != nil {
logs.Error("Error while parsing ")
return m, err
}
答案 0 :(得分:1)
我认为您要问的是更多关于何时打印错误而不是何时处理错误。就我而言,我喜欢打印所有日志,如果我认为它们将来对我有用的话。
对于您而言,消息logs.Error("Error while parsing ")
太冗长了,因为您在那里没有显示任何详细信息。
您可以考虑的其他方法是将自定义错误返回到顶层函数,而不是在更深层的函数中,仅在其中显示日志消息。在这个例子中,应该是这样的:
func main() {
bma, err := Parse("path")
if err != nil {
log.Println(err)
return
}
}
func Parse(source string) (bma.Bma, error) {
file, err := ioutil.ReadFile(source + "bma.yaml")
m := bma.Bma{}
if err != nil {
return m, fmt.Errorf("Not able to read the bma file: %s", err.Error())
}
err = yaml.Unmarshal([]byte(file), &m)
if err != nil {
return m, fmt.Errorf("Not able to unmarshal the bma file: %s", err.Error())
}
return m, err
}
答案 1 :(得分:0)
package main
import (
"fmt"
"log"
"os"
)
func main() {
fileName := "main.go"
err := parse(fileName)
if err != nil {
log.Println(err)
}
log.Println(parse2(fileName))
log.Println(parse3(fileName))
//Incase of library one need to create new errors and export them
//see error.go file of some stdlib packages for some example
}
func parse(s string) error {
_, err := os.Open(s + "t") // fails
if err != nil {
// no need to add any custom err information,
// as err contains required details (action, fileName, error)
return err
}
return nil
}
func parse2(s string) error {
// Incase you must handle errors
_, err := os.Open(s + "t") // fails
if err != nil {
err = (err.(*os.PathError)).Err //only, if you must handle it
if err == os.ErrPermission {
//send notification to developer, about user
} else if err == os.ErrNotExist {
//user is so irresponsible, block him
} else if os.IsNotExist(err) {
fmt.Println("found the cause")
}
return err
}
return nil
}
func parse3(s string) error {
err := badError(s)
if err != nil {
// wrap error with required context information,
// if err doesn't return proper error
// or if you have more useful information
return fmt.Errorf("%s ,%s", s, err)
}
return nil
}
func badError(s string) error {
return fmt.Errorf("badError,I'm not saying why it failed, and what's the argument which caused me to fail, and making error without actually any content")
}