Go里面的接口属于比较难理解的概念,通过它独特的错误处理方式可以帮助学习接口。

Go的错误类型使用error类型,它其实就是一个实现了Error()函数的接口:

type error interface {
    Error() string
}

所以再自定义一个错误类型,只需要实现其中的Error()函数即可。以官网给的练习为例:

package main

import (
	"fmt"
)

type ErrNegativeSqrt float64

func (e ErrNegativeSqrt) Error() string{
	var ans string
	ans=fmt.Sprintf("cannot Sqrt negative number: %v",float64(e))
	return ans
}

func Sqrt(x float64) (float64, error) {
	if x<0.0{
		return 0, ErrNegativeSqrt(x)
	}
	z:=float64(1)
	delta:=0.00001
	var temp float64
	for i:=0;i<10;i++{
		temp=z
		z=z-(z*z-x)/2.0/z;
		if(z-temp<delta){
			break;
		}
	}
	return z,nil
}

func main() {
	fmt.Println(Sqrt(2))
	fmt.Println(Sqrt(-2))
}
在上面的代码中,从float64实现了一个自定义类型ErrNegativeSqrt。我们需要error类型能返回一个字符串就行,但是这里想让它与数据有关,所以从float64来type。只要给它增加Error()方法,就可以在需要返回error类型的地方返回一个ErrNegativeSqrt,fmt会自动将Error()返回的字符串当做错误信息打印出来。(当然也可以通过Error()函数手动获得这个字符串)。接下来用从struct来type的自定义错误类型来重写上面那个程序:
package main

import (
	"fmt"
)

//自定义一个错误类型
//type ErrNegativeSqrt float64

//自定义一个错误类型
type Err struct {
	value float64
	info  string
}

//实现error接口
func (e Err) Error() string {
	e.info = fmt.Sprintf("cannot Sqrt negative number: %v", e.value)
	return e.info
}

/*//实现error接口
func (e ErrNegativeSqrt) Error() string {
	var ans string
	ans = fmt.Sprintf("cannot Sqrt negative number: %v", float64(e))
	return ans
}*/

//牛顿法求平方根
func Sqrt(x float64) (float64, error) {
	if x < 0.0 {
		var e Err
		e.value = x
		e.info = e.Error()
		return 0, e
	}
	z := float64(1)
	delta := 0.00001
	var temp float64
	for i := 0; i < 10; i++ {
		temp = z
		z = z - (z*z-x)/2.0/z
		if z-temp < delta {
			break
		}
	}
	return z, nil
}

func main() {
	fmt.Println(Sqrt(2))
	fmt.Println(Sqrt(-2))
}
这回把错误信息单独保存成一个字符串,可以随时调用该字段,上面两个程序的执行结果完全一样。