界面参考显示了奇怪的输出

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