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.
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.
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.
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