Golang Error Convert To String

学习 golang 的过程中,会在很多情况下接触 error,实际上是 interface 类型,下面是它的定义:

type error interface {
   Error() string
}

Go 语言的接口设计是非侵入式的,只要实现对应 interface 的方法就可以,所以只要实现 Error() 方法的类型都属于 error 接口类型。

创建 error 最简单的方法就是调用 errors.New 函数,其次还有一个方便的封装函数 fmt.Errorf(),会处理字符串格式化。系统中还有很多 error 的实现类型:PathError,syscall.Errno。

func main(){
	err := errors.New("create a error")
	fmt.Println("err:    ", err)			//err:     create a error
	fmt.Println("Error():", err.Error())	//Error(): create a error
}

注意下上面Println()的两种入参:打印结果是一样的。
事实上go有一个类似于java的 toString 方法,不过在go中它是一个接口,定义如下,只要实现了 String() 方法,调用 print 系列函数的时候就会执行。

type Stringer interface {
	String() string
}

但是 error 接口并没有实现 String() 方法,但是在打印的时候却可以直接输出,查看源码(src/fmt/print.go)发现,内部这里做了特殊处理,会利用反射机制+类型选择,自动匹配到error接口类型,然后调用Error()方法。

switch v := p.arg.(type) {
	case error:
		handled = true
		defer p.catchPanic(p.arg, verb, "Error")
		p.fmtString(v.Error(), verb) //这里调用Error()方法
		return

	case Stringer:
		handled = true
		defer p.catchPanic(p.arg, verb, "String")
		p.fmtString(v.String(), verb) //这里调用String()方法
		return
	}

上面除了调用 Error() 方法,根据类型选择也会调用 String() 方法,至此也就明白了,为什么可以直接打印error类型,同时所有实现Stringer接口的类型也可以直接调用print系列函数。

之前看的一篇文章 Go-Errors 也提到了这个情况,但是在 error 这一块并没有解释很清楚透彻。还有一篇文章 Be careful about printing error as string in GoLang
中用自定义的A类型实现了 Error() 方法然后打印报错了,因为入参的类型是 A 而不是 error,有兴趣可以试下,代码如下:

package main

import "fmt"

type A string

func (a A) Error() string {
	return fmt.Sprintf("%s is an error", a)
}

func main() {
	a := A("hello")
	fmt.Printf("error is %s", a)
}

你可能感兴趣的:(Go)