英文:
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))
}
我的问题:
当运行go test时,我收到以下错误消息:
fileLogger.File.data未定义(类型io.Writer没有字段或方法data)
file.Logger.File
确实是type io.Writer
,但是这个字段data
是存在的,我知道Go是一种强类型语言,所以它不接受这个。
如何解决这个问题?
英文:
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))
}
My problem:
I'm getting this error message when running go test:
fileLogger.File.data undefined (type io.Writer has no field or method data)
file.Logger.File
is indeed of type io.Writer
, but this field data
exists, I know Go is a strongly typed language, that's why it's not accepting this.
How can solve this?
答案1
得分: 3
在FileLogger
中,File
是一个接口(io.Writer
),而不是一个结构体。
要访问WriterMock
的data
,你需要进行类型断言:
fileLooger.File.(*WriterMock).data
(注意:如果File
不是*WriterMock
类型,这将失败:下面会详细说明)
请参考这个简化的示例:
package main
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 '[]'
由于类型断言可能出错,你应该始终检查错误,请参考“接口转换和类型断言”一节:
> 但是,如果发现值不包含字符串,程序将崩溃并出现运行时错误。
为了防止这种情况发生,可以使用“逗号,ok”的习惯用法来安全地测试值是否为字符串:
str, ok := value.(string)
if ok {
fmt.Printf("string value is: %q\n", str)
} else {
fmt.Printf("value is not a string\n")
}
英文:
The writer File
in a FileLogger
is an interface (io.Writer
), not a struct
.
You would need a type assertion in order to access data
of WriterMock
:
fileLooger.File.(*WriterMock).data
(Note: that would fail if File was not a *WriterMock
: more on that below)
package main
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)
}
Output:
Hello, playground '[]'
Since a type asertion car error, and you should always check the error, consider the section "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")
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论