英文:
Interface reference shows weird output
问题
我正在尝试理解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
为什么会这样呢?我期望输出的是"Error"和"Success",因为s
是Succer
类型的接口,没有返回错误字符串的方法。当我将main
函数改成以下形式时:
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
赋了一个引用。
英文:
I am trying to understand Go's interface concept and create following code:
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)
}
As output I've got
Error
Error
Why? I've expect as output error and success, because s
it is the interface of type Succer, there is no error return as string.
And when I change the main function like this:
func main() {
var r Result
var s Succer
c := &Combi{}
r = c
s = c
}
the compiler complain
# command-line-arguments
.\sample1.go:42: r declared and not used
.\sample1.go:43: s declared and not used
Why? I assign variables r
and s
a reference.
答案1
得分: 3
fmt.Println(s)
打印出"Error",因为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
,按照这个顺序获取要打印的值。
至于你最后一个问题,你必须使用一个变量,而不仅仅是赋值。打印它们会消除错误。
英文:
fmt.Println(s)
prints "Error" because error
is special-cased in the fmt
package
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
}
}
The fmt
package first checks if an object is a Formatter
, GoStringer
, error
, or Stringer
, in that order, to obtain a value to print.
As for your last question, you have to use a variable, not just assign it. Printing them removes the error.
答案2
得分: 2
关于你的第一个问题 - 如果你添加 fmt.Println(reflect.TypeOf(s))
- 你会发现输出不是 Succer
而是 *main.Combi
。
现在,由于它实现了 Error
接口并且有 Error() string
方法 - Println
认为它是一个 Go 错误对象并打印其 Error
方法的输出。
将 Error
方法更改为其他任何内容将阻止 Println(s)
打印 "Error"。但它也不会打印 "Success"。
英文:
Regarding your first question - if you add fmt.Println(reflect.TypeOf(s))
- you'll see that the output is not Succer
but *main.Combi
.
Now, since it implements the Error
interface and has Error() string
- Println
thinks it's a go error object and prints the output of its Error
method.
Changing the Error
method to anything else will stop Println(s)
from printing "Error". But it won't print "Success" either.
答案3
得分: 0
在你的第一个问题中,如果你想用s
调用一个success
函数来打印成功:
fmt.Println(s.Success())
至于第二个问题,Go
编译器会检查未使用的变量,所以只是赋值而没有使用会显示编译错误。
英文:
In your first question, if you want to print success with s
call a success
func:
fmt.Println(s.Success())
About the second question, Go
compiler check unused variables, so only assign it without use it show compilation error
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论