2015-12-07 52 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也分配元素。 –