fmt.Println调用Error而不是String()

Sri*_*isa 3 go

我有这个代码

package main

import (
    "fmt"
    "math"
)

type ErrNegativeSqrt float64

func (s ErrNegativeSqrt) String() string {
    return fmt.Sprintf("%f", float64(s))
}

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

func Sqrt(x float64) (ErrNegativeSqrt, error) {
    if x < 0 {
        e := ErrNegativeSqrt(x)
        return e, e
    } else {
        return ErrNegativeSqrt(math.Sqrt(x)), nil
    }
}

func main() {
    fmt.Println(Sqrt(2))
    fmt.Println(Sqrt(-2))
}
Run Code Online (Sandbox Code Playgroud)

这段代码的输出是

不能Sqrt负数:1.4142135623730951 <nil>不能Sqrt负数:-2不能Sqrt负数:-2

当我为ErrNegativeSqrt实现Stringer接口时,为什么fmt.Println调用Error()方法而不是String()方法?

我是新手,所以我可能会遗漏一些非常明显的东西.

Cer*_*món 9

文档说明了如何将值转换为字符串:

  1. 如果操作数实现了错误接口,则将调用Error方法将对象转换为字符串,然后根据动词的需要对其进行格式化(如果有).

  2. 如果操作数实现方法String()字符串,则将调用该方法将对象转换为字符串,然后根据动词(如果有)格式化该字符串.

error接口来之前Stringer.

编写函数的更惯用的方法是:

func Sqrt(x float64) (float64, error) {
  if x < 0 {
    return 0, ErrNegativeSqrt(x)
  }
  return math.Sqrt(x), nil
}
Run Code Online (Sandbox Code Playgroud)

  • 这是一个双参数返回值,因此不起作用.但坦率地说,这反映了一般的问题设计.函数可以返回多个值,因此当你只能传回一个错误本身(你正在做的事情,通过将两个相同的项目传回两次)时,你的结果项也没有真正的理由来实现错误接口.这里有代码异味. (3认同)