douou2026 2016-10-18 20:01
浏览 48
已采纳

为什么在键入断言接口时我的代码会慌乱?

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. 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. 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. 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. Am I correct in understanding this? Or is there something I'm missing?

  • 写回答

1条回答 默认 最新

  • dou91808 2016-10-18 21:23
    关注

    Ok Kaedys suggested that I change r := s.Index(i) Into: 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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 请教:如何用postman调用本地虚拟机区块链接上的合约?
  • ¥15 为什么使用javacv转封装rtsp为rtmp时出现如下问题:[h264 @ 000000004faf7500]no frame?
  • ¥15 乘性高斯噪声在深度学习网络中的应用
  • ¥15 运筹学排序问题中的在线排序
  • ¥15 关于docker部署flink集成hadoop的yarn,请教个问题 flink启动yarn-session.sh连不上hadoop,这个整了好几天一直不行,求帮忙看一下怎么解决
  • ¥15 深度学习根据CNN网络模型,搭建BP模型并训练MNIST数据集
  • ¥15 C++ 头文件/宏冲突问题解决
  • ¥15 用comsol模拟大气湍流通过底部加热(温度不同)的腔体
  • ¥50 安卓adb backup备份子用户应用数据失败
  • ¥20 有人能用聚类分析帮我分析一下文本内容嘛