繁体   English   中英

为什么当我输入 assert 接口时我的代码会发生恐慌?

[英]Why does my code panic when I type assert an interface?

我有一些服务器代码向端点发送请求并接收存储在空接口类型的对象中的 JSON 响应。 我必须解析信息并将其存储在“资源”对象的切片中,资源是一个接口。 在我的例子中,JSON 数据代表一个“Position”对象,它满足 Resource 接口。 所以基本上这些代码看起来像这样:

// 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()
}

位置模型是:

// 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)

我的端点旨在检索我的数据库中的位置列表,因此这显然意味着包含 JSON 数据的空接口包含一个资源切片,并且不能将类型断言到切片中(Go 不允许这样做)而是通过迭代手动完成。 所以我遵循了代码并将我的问题隔离为:

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
}

上面代码中的所有内容都运行良好,直到

ret[i] = rInterface.(Resource)

然后我的服务器炸毁和恐慌。 我查看了 Go 文档,据我所知,即使 rInterface 是一个带有 Position 模型数据的空接口,我也应该能够在 Resource 中输入 assert ,因为 Position 类型无论如何都满足 Resource 接口。 我的理解正确吗? 或者有什么我想念的吗?

Ok Kaedys 建议我将 r := s.Index(i) 改为: r := s.Index(i).Addr()

这确实奏效了,显然当您使用一个应该实现接口的对象时会出现问题,但是该对象上的所有方法都有指针接收器。 我只需要在接口中放入一个指向类型的指针。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM