我在[Go 系列教程31](https://studygolang.com/articles/12784)中看到 errors 包中的 New 函数的实现,猜测函数返回值是接口类型时,隐性地使用了接口。于是照抄了一份执行,但结果是指针,并不是预期那样
```go
type sr interface {
str() string
}
type es struct {
s string
}
func (e *es) str() string {
return e.s
}
//func (e *es) Error() string {
// return e.s
//}
func test(text string) sr {
return &es{text}
}
func main() {
fmt.Println(test("aaa"))
fmt.Println((&es{"bbb"}).str())
}
```
输出值如下:
```go
&{aaa}
bbb
```
更神奇的是我把上面注释的`Error()`方法取消注释,输出就像预期那样
```go
type sr interface {
str() string
}
type es struct {
s string
}
func (e *es) str() string {
return e.s
}
func (e *es) Error() string {
return e.s
}
func test(text string) sr {
return &es{text}
}
func main() {
fmt.Println(test("aaa"))
fmt.Println((&es{"bbb"}).str())
}
```
输出:
```go
aaa
bbb
```
这是为什么呢?我也没有使用`Error`方法。在很多在线代码运行工具上测试也是这样
更多评论
结构体有Error方法,即实现error接口,所以fmt.Println()内会执行p.fmtString(v.Error(), verb)
如果实现String()方法(即实现Stringer接口),也会有类似结果
如果两个同时实现,打印时Error()生效
```
switch verb {
case 'v', 's', 'x', 'X', 'q':
// Is it an error or Stringer?
// The duplication in the bodies is necessary:
// setting handled and deferring catchPanic
// must happen before calling the method.
switch v := p.arg.(type) {
case error:
handled = true
defer p.catchPanic(p.arg, verb, "Error")
p.fmtString(v.Error(), verb)
return
case Stringer:
handled = true
defer p.catchPanic(p.arg, verb, "String")
p.fmtString(v.String(), verb)
return
}
}
```
#1