英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论