接口参考显示奇怪的输出

时间:2015-03-17 15:26:58

标签: go

我试图了解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

为什么呢?我为变量rs指定了参考。

3 个答案:

答案 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包首先按顺序检查某个对象是FormatterGoStringererror还是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编译器检查未使用的变量,所以只分配它而不使用它显示编译错误