英文:
Is an embedded error exported?
问题
根据Go语言规范,我可以在结构体中嵌入一个类型。
对于error接口有一个奇怪的情况。它的首字母没有大写,所以我认为它不是作为一个类型导出的。但它是由语言定义的。所以如果我有一个如下的结构体:
package foo
type Err struct {
error
}
嵌入的error是否被导出?Err是否满足error接口?
我可以从另一个包中访问它吗?也就是下面的代码是否正确?
package main
import "errors"
import "fmt"
import "foo"
func main() {
e := foo.Err{}
e.error = errors.New("Hello world!") // 这样可以吗?
fmt.Println(e.Error())
}
英文:
According to the Go language spec, I can embed a type in a struct.
There is a weird case with the error interface. It is not uppercased, so I assume it is not exported as a type. But it is defined by the language. So if I have a struct like this:
package foo
type Err struct {
error
}
is the embedded error exported? Does Err satisfy the error interface?
Can I access it from another package, i.e. is the following ok?
package main
import "errors"
import "fmt"
import "foo"
func main() {
e := foo.Err{}
e.error = errors.New("Hello world!") // is this okay?
fmt.Println(e.Error())
}
答案1
得分: 5
当你将一个error接口嵌入到一个结构体中时,基本上是在它中添加了一个名为error、类型为error的字段。
因为它是嵌入的,所以你的结构体现在也实现了它的所有方法。这意味着你的结构体满足了error接口,你可以在它上面调用Error()方法,或者直接将它传递给Println,它会将其类型断言为error并为你调用Error()方法。https://play.golang.org/p/0VxUUX2l-z
显然,由于字段名为error,它是不可导出的。但是,该结构体仍然满足error接口,因为它有Error()方法。
有趣的结果是,如果你不初始化该字段,Println会引发恐慌,因为它将尝试在nil上调用Error()方法。https://play.golang.org/p/XctFgKZI-K
英文:
When you embed an error interface into a struct, basically, you add a field named error with type error to it.
Because it's embedded your struct now also implements all of it's methods. That means your struct satisfies the error interface and you can call Error() on it or just pass it to Println as it is and it will type assert it into error and call Error() for you https://play.golang.org/p/0VxUUX2l-z
Obviously, because field is named error it's not exported. But the struct still satisfies the error interface because it has Error() method.
Interesting consequence of this is that if you don't initialize the field Println will panic because it will try to call Error() on nil https://play.golang.org/p/XctFgKZI-K
答案2
得分: 0
e := foo.Err{}
e.error = errors.New("你好,世界!") // 错误
这会导致错误,因为e.error在包外部是不可访问的。
如果你需要设置这个字段,你可以声明一个构造函数:
func NewError(err error) *Error {
return &Error{error: err}
}
但是如果你真的需要导出这个字段,这仍然是可能的:你可以声明一个类型别名:
type Error struct {
Err
}
type Err = error
然后你可以从包外部访问e.Err字段。
英文:
e := foo.Err{}
e.error = errors.New("Hello world!") // error
This will cause an error since e.error is not accessible from outside package.
If you need to set this field, you may declare a constructor:
func NewError(err error) *Error {
return &Error{error: err}
}
But if you really need to export this field, this is still possible: you may declare a type alias:
type Error struct {
Err
}
type Err = error
Then you may access e.Err field from outside package.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论