为什么 errorString 是一个结构体,而不是一个字符串

我正在阅读 The Go Programming Language 一书,并在其中描述了错误包和接口


package errors


type error interface {

    Error() string

}


func New(text string) error { return &errorString{text} }


type errorString struct { text string }


func (e *errorString) Error() string { return e.text }

它说


errorString 的底层类型是一个结构体,而不是一个字符串,以保护其表示免受无意(或有预谋的)更新。


这是什么意思?由于errorString未导出,包不会隐藏底层类型吗?


更新 这是我errorString使用 a实现的测试代码string。请注意,当尝试从另一个包中使用它时,您不能仅将字符串分配为错误。


package testerr


type Error interface {

        Error() string

}


func New(text string) Error {

        return errorString(text)

}


type errorString string


func (e errorString) Error() string { return string(e) }

并使用建议的代码对其进行测试


func main() {

    err := errors.New("foo")

    err = "bar"

    fmt.Prinln(err)

}

编译时最终会产生错误


cannot use "bar" (type string) as type testerr.Error in assignment:

    string does not implement testerr.Error (missing Error method)


当然,这有一个缺点,因为碰巧具有相同错误字符串的不同错误将评估为相等,这是我们不想要的。


桃花长相依
浏览 313回答 2
2回答

MM们

这本书关于“保护表示免受无意更新”的解释对我来说似乎具有误导性。无论errorString是结构体还是字符串,错误信息仍然是字符串并且字符串是不可变的规范。这也不是关于独特性的辩论。例如,errors.New("EOF") == io.EOF计算结果为false,尽管两个错误具有完全相同的基础消息。即使errorString是字符串,只要errors.New返回指向它的指针,同样适用(参见我的示例。)您可以说结构体实现error是惯用的,因为这也是标准库引入自定义错误的方式。SyntaxError从encoding/json包装上看:type SyntaxError struct {        Offset int64 // error occurred after reading Offset bytes        // contains filtered or unexported fields}func (e *SyntaxError) Error() string { return e.msg }此外,实现error接口的结构没有性能影响,并且不会比字符串实现消耗更多内存。请参阅Go 数据结构。

Qyouu

您的 testerr 包运行良好,但它失去了“基于结构的”标准错误包的一个主要功能:不等式:package mainimport ( "fmt"; "testerr";  "errors" )func main() {    a := testerr.New("foo")    b := testerr.New("foo")    fmt.Println(a == b)  // true    c := errors.New("foo")    d := errors.New("foo")    fmt.Println(c == d)  // false}随着errorString作为一个普通的字符串相同的字符串内容不同的错误相等。原始代码使用一个指向 struct 的指针,并且每个都New分配一个新的 struct,因此New如果与==相同的错误文本进行比较,则返回的不同值是不同的。不允许编译器在此处生成相同的指针。而“对 New 的不同调用会产生不同的错误值”这一特性对于防止意外的错误相等很重要。您可以通过*errorString执行来修改您的测试器以产生此属性Error。试试看:你需要一个临时取的地址。“感觉”不对。可以想象一个花哨的编译器,它内部化字符串值并可能返回相同的指针(因为它指向相同的内部化字符串),这会破坏这个很好的不等式属性。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go