java系统找不到指定文件怎么解决
290
2022-09-16
【Go进阶训练营】Go语言实践-error
Error vs Exception
Go error 就是普通的一个接口,普通的值。
type error interface { Error() string}
大部分时候使用errors.New(“”)返回一个对象
func New(text string) error { return &errorString{text} //这里返回的是一个指针}type errorString struct { s string}//errorString实现了error接口的Error方法 func (e *errorString) Error() string { return e.s}
不同语言异常处理
各个语言的演进历史: C 单返回值,一般通过传递指针作为入参,返回值为 int 表示成功还是失败。
ngx_int_t ngx_create_path(ngx_file_t *file, ngx_path_t *path);
C++ 引入了 exception,但是无法知道被调用方会抛出什么异常。
Java 引入了 checked exception,方法的所有者必须申明,调用者必须处理。在启动时抛出大量的异常是司空见惯的事情,并在它们的调用堆栈中尽职地记录下来。Java 异常不再是异常,而是变得司空见惯了。它们从良性到灾难性都有使用,异常的严重性由函数的调用者来区分。
java.Error & java.RuntimeException
go error and exception
Go 的处理异常逻辑是不引入 exception,支持多参数返回,所以你很容易的在函数签名中带上实现了 error interface 的对象,交由调用者来判定。 如果一个函数返回了 (value, error),你不能对这个 value 做任何假设,必须先判定 error。唯一可以忽略 error 的是,如果你连 value 也不关心。 Go 中有 panic 的机制,如果你认为和其他语言的 exception 一样,那你就错了。当我们抛出异常的时候,相当于你把 exception 扔给了调用者来处理。 比如,你在 C++ 中,把 string 转为 int,如果转换失败,会抛出异常。或者在 Java 中转换 String 为 Date 失败时,会抛出异常。 Go panic 意味着 fatal error(就是挂了)。不能假设调用者来解决 panic,意味着代码不能继续运行。
使用多个返回值和一个简单的约定,Go 解决了让程序员知道什么时候出了问题,并为真正的异常情况保留了 panic。
func Positive(n int) bool { if n == 0 { panic("n undefined") } return n > -1}func Check(n int) { defer func() { if recover() != nil { fmt.Println("is neither") } }() if Positive(n) { fmt.Println(n, "is positive") } else { fmt.Println(n, "is negative") }}func main() { Check(9)}
对于真正意外的情况,那些表示不可恢复的程序错误,例如索引越界、不可恢复的环境问题、栈溢出,我们才使用 panic。对于其他的错误情况,我们应该是期望使用 error 来进行判定。 You only need to check the error value if you care about the result. – Dave 简单 考虑失败,而不是成功(plan for failure, not success) 没有隐藏的控制流 完全交给你来控制 error Error are values
Error Type
Sentinel Error
预定义的特定错误,我们叫为 sentinel error,这个名字来源于计算机编程中使用一个特定值来表示不可能进行进一步处理的做法。所以对于 Go,我们使用特定的值来表示错误。 if err == ErrSomething { … } 类似的 io.EOF,更底层的 syscall.ENOENT。
Error types
与刚开始我们使用的错误值比较,错误类型内部进行封装详细的错误信息,可以提供给调用者较多的上下文信息。唯一的缺点是 要使用调用者需要使用类型断言进行处理,而这种形式和调用者是强耦合的形式。
type MyError struct { Msg string File string Line int}func (e *MyError) Error() string { return fmt.Sprintf("%s:%d:%s", e.File, e.Line, e.Msg)}func test() error { return &MyError{"something", "file read", 10}}//假设Test不在和MyError同一个包中,那么MyError属性需要公开,TestMyErrors才可以访问到。func TestMyErrors(t *testing.T) { err := test() switch e := err.(type) { case nil: case *MyError: fmt.Println("error occurred on line",err, e.Line) default: }}
建议:避免使用error types,虽然能提供较多的错误上下文信息,但是会导致API变的更加脆弱。
不透明错误处理方式
最灵活的处理方式是不关注调用方法内部的错误信息,如果出现错误,直接向上层方法进行传递。也即不透明错误处理方式。只返回错误而不建设其内容,但是这种方式就是出现错误后,不容易找到异常点。
func fn() error { open, err := os.Open("is") if err != nil { return err } fmt.Println(open) return nil}
复盘
errorCode 建议总结
1.通常来说 我们可能处理一个函数的error,而应该将正常的流程进行书写成一条直线,而不是锁进的代码。主要的好处是可以比较直观的看到程序正常流程执行顺序,否则的话 对于正常流程的梳理比较花费较大的精力。
//不推荐 open, err := os.Open("abc") if err == nil { //do } //推荐 open, err := os.Open("abc") if err != nil { //log } //do continue something
引用
Go 2 Error Inspection https://commandcenter.blogspot.com/2017/12/error-handling-in-upspin.html
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~