2015-12-07 53 views
3

我最近开始使用Google App Engine上的Go进行编程,并且遇到了路障。我来自爪哇岛,所以在适应Go方面进行了轻微的斗争。切片和界面操作

我想要一种方法,允许我传入一个指向切片的指针,然后我可以传入datastore.GetAll调用来检索结果。然后,我想遍历结果并使用断言来将其转换为特定的接口(Queryable),以便调用方法Map()。

起初,我有这个正常:

func (s ProjectService) RunQuery(context context.Context, q *datastore.Query, projects *[]Project) error { 
    keys, err := q.GetAll(context, projects) 
    if err != nil { 
     return err 
    } 

    for i, key := range keys { 
     (*projects)[i].Id = key.Encode() 
     (*projects)[i].CompanyId = (*projects)[i].Company.Encode() 
    } 
    return nil 
} 

我想有一个可以被应用到实现Queryable接口的任何实体,一个更通用的方法。这个想法是让我在检索结果后执行一些后处理。我查看了ProperyLoadSaver接口,但是我无法访问与实体关联的实际密钥。我想在实体中存储datastore.Key的字符串表示形式。

这是Queryable接口:

type Queryable interface { 
    Map(*datastore.Key) error 
} 

下面是我坚持到GAE店为例实体:

type Camera struct { 
    Id  string `datastore:"-"` 
    ProjectId string `datastore:"-"` 
    Name  string 
    Project *datastore.Key `json:"-"` 
    Active bool 
    Timestamp Timestamp 
} 

// Implement Queryable interface. Let me perform any additional mapping 
func (c *Camera) Map(key *datastore.Key) error { 
    c.Name = "Maybe do other things here" 
    c.Id = key.Encode() 
    return nil 
} 

的想法是有一些像下面的代码片段。

func (c Crud) RunQuery(context context.Context, q *datastore.Query, entities interface{}) error { 
    keys, err := q.GetAll(context, entities)  
    v := reflect.ValueOf(entities) 
    dv := v.Elem() 

    for i, key := range keys {   
// I left this in to show that this worked however this won't let me enforce the interface contract 
//dv.Index(i).FieldByName("Id").Set(reflect.ValueOf(key.Encode())) 

     entity := dv.Index(i).Interface().(Queryable) 
     entity.Map(key)  
    } 

    return err 
} 

然而,这种执行时,恐慌有以下:

PANIC: interface conversion: entity.Camera is not entity.Queryable: missing method Map goroutine 9 [running]:

正如一个音符,我认识到执行断言适当的方法是做的,如果是,ok := elem.(Type); ok {}但我只是想看看错误是什么

我猜我得到这个错误,因为我已经定义了我的参数与指针接收器func (c *Camera) Map(key *datastore.Key) error和没有tfunc (c Camera) Map(key *datastore.Key) error但是,我想修改实际值。

我在哪里出错了?我的Java内核是否显示?

因为我对Go非常陌生,所以我可能会接近完全错误的。

回答

1

因为该方法是在一个指针接收器(因为它应该是),使用切片元件的address

entity := dv.Index(i).Addr().Interface().(Queryable) 

的另一种方法是使用用于结果的指针的切片:

var result []*Camera 
err := c.RunQuery(ctx, q, &result) 

的代码可以被写入与两个[]相机工作或[] *相机如下:

var queryableType = reflect.TypeOf((*Queryable)(nil)).Elem() 
needAddr := !dv.Type().Implements(queryableType) 

... 

var entity Queryable 
if needAddr { 
    entity = dv.Index(i).Addr().Interface().(Queryable) 
} else { 
    entity = dv.Index(i).Interface().(Queryable) 
} 
+0

'Addr()'把我从那个泡菜里拿出来了。此外,没有意识到我可以使用[] *相机vs * []相机。这是我需要阅读的其他内容。 –

+0

GetAll支持* [] Camera和* [] * Camera的结果参数类型。在这两种情况下,GetAll都会分配结果片。在第二种情况下,GetAll也分配元素。 –