[英]Why does my code panic when I type assert an interface?
I have some server code that sends a request to an endpoint and receives a JSON response which is stored in an object that is of type empty interface.我有一些服务器代码向端点发送请求并接收存储在空接口类型的对象中的 JSON 响应。 I have to parse out the information and store it in a slice of "Resource" objects, with Resource being an interface.
我必须解析信息并将其存储在“资源”对象的切片中,资源是一个接口。 The JSON data in my case represents a "Position" object, which satisfies the Resource interface.
在我的例子中,JSON 数据代表一个“Position”对象,它满足 Resource 接口。 So basically the code for these look like this:
所以基本上这些代码看起来像这样:
// Resource interface type
type Resource interface {
// Identifier returns the id for the object
Identifier() bson.ObjectId
// Description give a short description of the object
Description() string
// Initialize should configure a resource with defaults
Initialize()
// Collection name for resource
Collection() string
// Indexes for the resources
Indexes() []mgo.Index
// UserACL returns the user access control list
UserACL() *UserACL
// IsEqual should compare and return if resources are equal
IsEqual(other Resource) bool
// Refresh should update a resource from the database
Refresh()
}
And the position model is:位置模型是:
// Position model
type Position struct {
ID bson.ObjectId `json:"id" bson:"_id,omitempty" fake:"bson_id"`
Title string `json:"title" bson:"title" fake:"job_title"`
Summary string `json:"summary" bson:"summary,omitempty" fake:"paragraph"`
IsCurrent bool `json:"isCurrent" bson:"is_current,omitempty" fake:"bool"`
CompanyID bson.ObjectId `json:"company" bson:"company_id,omitempty" fake:"bson_id"`
UACL *UserACL `bson:"user_acl,omitempty" fake:"user_acl"`
}
// Identifier returns the id for the object
func (p *Position) Identifier() bson.ObjectId {
return p.ID
}
// Description give a short description of the object
func (p *Position) Description() string {
return fmt.Sprintf("[%v:%v]", p.Collection(), p.ID)
}
....(the other methods follow)
My endpoint is designed to retrieve a list of positions in my database, so this obviously means that the empty interface containing the JSON data contains a slice of Resources, and can't be type asserted into a slice (Go doesn't allow this) and instead done manually by iteration.我的端点旨在检索我的数据库中的位置列表,因此这显然意味着包含 JSON 数据的空接口包含一个资源切片,并且不能将类型断言到切片中(Go 不允许这样做)而是通过迭代手动完成。 So I followed through the code and isolated my problem to this:
所以我遵循了代码并将我的问题隔离为:
func InterfaceSlice(slice interface{}) []Resource {
s := reflect.ValueOf(slice).Elem()
if s.Kind() != reflect.Slice {
panic("InterfaceSlice() given a non-slice type")
}
ret := make([]Resource, s.Len())
for i := 0; i < s.Len(); i++ {
r := s.Index(i)
rInterface := r.Interface()
ret[i] = rInterface.(Resource)
}
return ret
}
Everything in the above code is working just fine until上面代码中的所有内容都运行良好,直到
ret[i] = rInterface.(Resource)
and then my server blows up and panics.然后我的服务器炸毁和恐慌。 I looked through the Go documentation and as far as I can tell I should be able to type assert into Resource even though rInterface is an empty interface with Position model data because the Position type satisfies the Resource interface anyway.
我查看了 Go 文档,据我所知,即使 rInterface 是一个带有 Position 模型数据的空接口,我也应该能够在 Resource 中输入 assert ,因为 Position 类型无论如何都满足 Resource 接口。 Am I correct in understanding this?
我的理解正确吗? Or is there something I'm missing?
或者有什么我想念的吗?
Ok Kaedys suggested that I change r := s.Index(i) Into: r := s.Index(i).Addr() Ok Kaedys 建议我将 r := s.Index(i) 改为: r := s.Index(i).Addr()
And this did the trick, apparently the problem occurs when you use an object that is supposed to fulfill an interface, but all the methods on that object have pointer receivers.这确实奏效了,显然当您使用一个应该实现接口的对象时会出现问题,但是该对象上的所有方法都有指针接收器。 I just needed to put a pointer to the type into the interface.
我只需要在接口中放入一个指向类型的指针。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.