Go:属性存在,但Go编译器说它没有?

时间:2015-03-08 15:42:30

标签: go tdd

filelogger.go

package logger

import (
    "io"
)

type FileLogger struct{
    File io.Writer
}

func NewFileLogger(file io.Writer) *FileLogger{
    return &FileLogger{file}
}

func (this *FileLogger) Log(message string) error {
    _, err := this.File.Write([]byte(appendNewLine(message)))

    return err
}

filelogger_test.go:

package logger

import (
    "testing"

    "github.com/stretchr/testify/assert"
)

type WriterMock struct{
    data []byte
}

func (this WriterMock) Write(b []byte) (n int, err error) {
    this.data = append(this.data, b ...)

    return len(this.data), nil
}

func NewMockedFileLogger() *FileLogger{
    writer := WriterMock{}

    fileLogger := FileLogger{writer}

    return &fileLogger
}

func TestLog(t *testing.T) {
    fileLogger := NewMockedFileLogger()

    fileLogger.Log("Hello World!")

    assert.Equal(t, "Hello World!", string(fileLogger.File.data))
}

我的问题:

我在运行go test时收到此错误消息:

fileLogger.File.data undefined (type io.Writer has no field or method data)

file.Logger.File确实属于type io.Writer,但此字段data存在,我知道Go是一种强类型语言,这就是为什么它不接受这个。

怎么能解决这个问题?

1 个答案:

答案 0 :(得分:3)

File中的作者FileLoggerinterfaceio.Writer),而不是struct

您需要 type assertion 才能访问data的{​​{1}}:

WriterMock

(注意:如果文件不是fileLooger.File.(*WriterMock).data ,则会失败:更多内容如下)


请参阅this simplified example

package main

*WriterMock

输出:

import "fmt"
import "io"

type WriterMock struct {
    data []byte
}

func (this WriterMock) Write(b []byte) (n int, err error) {
    this.data = append(this.data, b...)

    return len(this.data), nil
}

func main() {
    var w io.Writer = &WriterMock{}
    fmt.Printf("Hello, playground '%+v'", w.(*WriterMock).data)
}

----

由于类型asertion汽车错误,您应该始终检查错误,请考虑" Interface conversions and type assertions"

部分
  

但如果事实证明该值不包含字符串,则程序将因运行时错误而崩溃   为防止这种情况,请使用"逗号,确定"习惯用来安全地测试值是否为字符串:

Hello, playground '[]'