Skip to the content.

https://tour.go-zh.org/这个链接是中文版Go指南的官网,下面只记录一些比较抽象的知识点,不会全部记载。

1. Methods,Interface

1.1 Error

Go 程序使用 error 值来表示错误状态。下面给出一个具体例子:

package main
import ("fmt" "time")
type MyError struct {
	When time.Time
	What string
}
func (e *MyError) Error() string {
	return fmt.Sprintf("at %v, %s",
		e.When, e.What)
}
func run() error {
	return &MyError{ time.Now(),"it didn't work",}
}
func main() {
	if err := run(); err != nil {
		fmt.Println(err)
	}
}

在Go语言中,error是一个内建的接口类型,它定义了一个方法Error() string。任何实现了这个方法的类型都可以被认为是一个error类型。在您的代码中,MyError类型实现了Error()方法,所以它可以被当作error类型来使用。

当您在run()函数中返回一个*MyError类型的值时,由于它实现了error接口,所以可以被当作error类型来使用。这就是为什么run()函数的返回值类型可以是error,尽管我们实际上返回的是一个MyError类型的值。

至于为什么调用fmt.Println(err)就相当于调用了接收者函数Error(),这是因为当我们尝试打印一个错误时,Go语言会自动调用该错误类型实现的Error()方法来获取错误的字符串表示形式。所以,在您的代码中,当我们尝试打印错误时,Go语言会自动调用您定义的MyError.Error()方法来获取错误信息。这就是为什么打印错误时会输出您在Error()方法中定义的字符串。这种机制使得我们可以自定义错误信息的格式和内容。

1.2 Error练习

之前的练习中复制 Sqrt 函数,修改它使其返回 error 值。

Sqrt 接受到一个负数时,应当返回一个非 nil 的错误值。复数同样也不被支持。

创建一个新的类型

type ErrNegativeSqrt float64

并为其实现

func (e ErrNegativeSqrt) Error() string

方法使其拥有 error 值,通过 ErrNegativeSqrt(-2).Error() 调用该方法应返回 "cannot Sqrt negative number: -2"

注意:Error 方法内调用 fmt.Sprint(e) 会让程序陷入死循环。可以通过先转换 e 来避免这个问题:fmt.Sprint(float64(e))。这是为什么呢?

修改 Sqrt 函数,使其接受一个负数时,返回 ErrNegativeSqrt 值。

package main

import ("fmt""math")

type ErrNegativeSqrt float64

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

func Sqrt(x float64) (float64, error){
	if (x < 0) {
		return 0,ErrNegativeSqrt(x)
	}
	z := 1.4 
    prez := 0.0
	for z - prez > math.Pow(2,-20) {
		prez = z
		z -= (z*z - x) / (2*z)
		fmt.Println("current z is:", z)
	}
	return z,nil
}

func main() {
	fmt.Println(Sqrt(2))
	_,err := fmt.Println(Sqrt(-2))
	if (err != nil) {
		fmt.Println(err)
	}
}

back.