我试图了解Go的界面概念并创建以下代码:
package main
import "fmt"
type Failer interface {
Error() string
}
type Succer interface {
Success() string
}
type Result interface {
Failer
Succer
}
type Fail struct{}
func (*Fail) Error() string {
return "Error"
}
type Succ struct{}
func (*Succ) Success() string {
return "Success"
}
type Combi struct{}
func (*Combi) Error() string {
return "Error"
}
func (*Combi) Success() string {
return "Success"
}
func main() {
var r Result
var s Succer
c := &Combi{}
r = c
s = c
fmt.Println(r.Error())
fmt.Println(s)
}
作为输出我已经
Error
Error
为什么呢?我预计输出错误和成功,因为s
它是Succer类型的接口,没有错误返回为字符串。
当我改变主要功能时:
func main() {
var r Result
var s Succer
c := &Combi{}
r = c
s = c
}
编译器抱怨
# command-line-arguments
.\sample1.go:42: r declared and not used
.\sample1.go:43: s declared and not used
为什么呢?我为变量r
和s
指定了参考。
答案 0 :(得分:3)
fmt.Println(s)
打印“错误”,因为error
包中的fmt
是特殊的
switch v := p.arg.(type) {
case error:
handled = true
defer p.catchPanic(p.arg, verb)
p.printArg(v.Error(), verb, depth)
return
case Stringer:
handled = true
defer p.catchPanic(p.arg, verb)
p.printArg(v.String(), verb, depth)
return
}
}
fmt
包首先按顺序检查某个对象是Formatter
,GoStringer
,error
还是Stringer
,以获取值打印。
至于你的上一个问题,你必须使用一个变量,而不仅仅是分配它。打印它们可以消除错误。
答案 1 :(得分:2)
关于您的第一个问题 - 如果您添加fmt.Println(reflect.TypeOf(s))
- 您会看到输出不是Succer
而是*main.Combi
。
现在,由于它实现了Error
接口并且Error() string
- Println
认为它是一个go错误对象并打印其Error
方法的输出。
将Error
方法更改为其他任何内容都会导致Println(s)
停止打印"错误"。但它不会打印"成功"任
答案 2 :(得分:0)
在第一个问题中,如果您想通过s
打印成功,请拨打success
func:
fmt.Println(s.Success())
关于第二个问题,Go
编译器检查未使用的变量,所以只分配它而不使用它显示编译错误