困惑:在Go中实现多个接口

时间:2016-05-05 18:46:48

标签: go interface

在下面的代码中,类型ErrNegativeSqrt实现了Stringererror接口。由于在Sqrt方法中返回类型为fmt.Stringer,我将执行结果除外:

  

0 nil

     

0 Impl Stringer type

但实际结果如下,为什么?

  

0 nil

     

0 Impl错误类型

package main

import (
    "fmt"
)

type ErrNegativeSqrt float64

func Sqrt(x ErrNegativeSqrt) (float64, fmt.Stringer) {
    if x < 0 {
        return 0, ErrNegativeSqrt(x)
    }
    return 0, nil
}

func (e ErrNegativeSqrt) String() string {
    return "Impl Stringer type"
}

func (e ErrNegativeSqrt) Error() string {
    return "Impl error type"
}

func main() {
    fmt.Println(Sqrt(2))
    fmt.Println(Sqrt(-2))
}

2 个答案:

答案 0 :(得分:5)

documentation for Package fmt表示:

  

...特殊格式   注意事项适用于实现某些接口的操作数。   按申请顺序:

     

...

     
      
  1. 如果%v动词与#flag(%#v)一起使用,并且操作数实现了GoStringer接口,那么将调用它。
  2.         

    如果格式(对于Println等隐式为%v)对a有效   字符串(%s%q%v%x%X),适用以下两个规则:

         
        
    1. 如果操作数实现了错误接口,则将调用Error方法...

    2.   
    3. 如果操作数实现方法String()字符串,则将调用该方法...

    4.   

由于您使用的是fmt.Println,因此规则4和5会发挥作用,而Error()优先于String()

答案 1 :(得分:3)

您通过将结果值作为fmt.Stringer传递给fmt.Println,忽略了您的函数返回interface{}的事实。

您只能看到Error()方法的结果,因为fmt包在检查error接口之前会检查fmt.Stringer接口。