Go: 属性 存在但 Go 编译器说它不存在?

Go: Property exists but Go compiler says it doesn't?

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))
}

我的问题:

我在 运行 进行测试时收到此错误消息:

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

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

如何解决这个问题?

FileLogger 中的作者 Fileinterface (io.Writer),而不是 struct

您需要 type assertion 才能访问 data of WriterMock:

fileLooger.File.(*WriterMock).data

(注意:如果 File 不是 *WriterMock,那将失败:下面有更多内容)


this simplified example:

主要包

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)
}

输出:

Hello, playground '[]'

----

由于类型断言汽车错误,您应该始终检查错误,请考虑“Interface conversions and type assertions”部分:

But if it turns out that the value does not contain a string, the program will crash with a run-time error.
To guard against that, use the "comma, ok" idiom to test, safely, whether the value is a string:

str, ok := value.(string)
if ok {
    fmt.Printf("string value is: %q\n", str)
} else {
    fmt.Printf("value is not a string\n")
}