Go语言中的错误处理系统

Go语言中的错误处理系统

原文链接:http://blog.csdn.net/cc7756789w/article/details/51014076
作者:牧歌
github:https://github.com/ZhangHang-z
转载请注明出处,未经作者允许不可用于商业目的。


侵入式接口和Go的非侵入式接口

Go语言中没有其他语言try....catch的语法,因为Go语言的特殊的接口类型,不需要侵入式地去实现接口,自定义错误类更为简单。

先来介绍Go中接口的使用方法,需要理解一个概念:Go中任何实现了某个接口所定义函数的类都可以被赋值给接口类型。

先来看一下Java中是怎么实现接口的:

public interface Bird {
    void fly()
    boolean haveFeather()
}

public interface Animal {
    void run()
}

// 侵入式实现接口
public class Little implements Animal, Bird {
    @Override
    public void run() {
        System.out.println("running...")
    }

    @Override
    public void fly() {
        System.out.println("I'm flying...")
    }

    @Override
    public boolean haveFeather() {
        return true
    }
}

Go是这样实现的:


import "fmt"

type Human struct {
    name string
    age  uint8
}

func (h *Human) PrtCountry(c string) error {
    fmt.Printf("%s was %d years old, and he from %s\n", h.name, h.age, c)
    return nil
}

func (h *Human) PrtLang(lang string) error {
    fmt.Printf("%s was %d years old, and he speak %s\n", h.name, h.age, lang)
    return nil
}

type China interface {
    PrtCountry(c string) error
}

func main() {
    var person1 *Human = &Human{"bob", 22}
    person1.PrtCountry("Wuxi")

    var person2 China = person1
    person2.PrtCountry("Suzhou")
}
>>> [ `go run errors_test1.go` | done: 971.446272ms ]
>>> bob was 22 years old, and he from Wuxi
>>> bob was 22 years old, and he from Suzhou

我们看到,Go只需要把一个实现了接口所需函数的对象赋值给对象类型就可以,当然我举得例子并不恰当,另外关于指针对象和值对象的区别请自行阅读书籍或文档。

error接口的定义

下面我们来直入主题,错误处理是一门优秀的语言必不可缺的,那么Go中是如何实现的呢?

查看官网的语言定义Expressions Errors上我们发现:

这里写图片描述
(额,万恶的XXX,如果打不开可以在命令行输入godoc -http ":9999"然后浏览器中输入127.0.0.1:999打开godoc内置的文档服务器,Win和Linux一样)

我的英文也不咋的,大概是说:

// 预先声明类型error被定义为:
type error interface {
    Error() string
}

// 这个约定俗成的接口用来表现出一个error条件
// 返回nil表示没有发生error
// 下面是一个函数返回error的用法....
func Read(f *File, b []byte) (n int, err error)

error接口的定义非常简洁,你只需要实现Error函数就可以自定义一个Error处理类,我们来自定义一个error类型:

package main

import "fmt"

type MyError struct {
    errString string
}

func (e MyError) Error() string {
    return e.errString
}

func outError() error {
    return MyError{
        "Always this, fuck my Error.",
    }
}

func main() {
    if err := outError(); err != nil {
        fmt.Println(err)
    }
}

>>> [ `go run error_test2.go` | done: 857.997463ms ]
>>> Always this, fuck my Error.

刚才我们讲过接口赋值,如果你明白了接口赋值是怎么工作,那么不难理解为什么可以这样返回error类型,其实就相当于做了如下工作:

var err error = MyError{"Always this, fuck my Error."}
return err

(当然这里的err传递的都是值语义,并非引用)

这个例子在errors文档也有Example

标准库errors.go

errors.go标准库的源码只有几行,其中给我们封装了一个建议的错误处理函数:

// Package errors implements functions to manipulate errors.
package errors

// New returns an error that formats as the given text.
func New(text string) error {
    return &errorString{text}
}

// errorString is a trivial implementation of error.
type errorString struct {
    s string
}

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

这个New方法的作用你可以比作为工厂函数,利用它我们不必自己再重复写自定义错误类来赋值给error接口。

func main() {
    err := errors.New("Fuck my error")
    if err != nil {
        fmt.Println(err)
    }
}

>>> Fuck my error

如果我们需要使用%s %d这样格式化输入来生成errfmt包提供了Errorf函数:

const eName, id = "Internal Error", "12345"
func main() {
    err := fmt.Errorf("Error: %s occured, time: %s", eName, id)
    if err != nil {
        fmt.Println(err)
    }
}

总结

Go中只要实现了Error函数的类都可以赋值给error接口,没有错误只需要返回nil。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值