2016-05-29 15 views
1

Gorillaツールキットのsessionsパッケージを使用して、カスタム構造インスタンスの配列を格納して取得する必要のあるプログラムを開発しています。カスタム構造を復元するには、リフレクション機能を使用する必要があります。問題は、Timestampという名前の構造に2つのtime.Timeインスタンスが含まれており、インスタンスを復元できなかったことです。したがって、私の質問は、time.Timeインスタンスを復元する方法です。Reflection - restore time.Time instance

以下はTimespan構造のコードと、Timespan配列をセッションストアに格納して読み取るコードです。あなたは、フィールドへのインターフェイスを取得する必要があり

type Timespan struct { 
    ID uint8; 
    StartDate time.Time; 
    EndDate time.Time; 
} 

func (server *WebServer) setTimespans(writer http.ResponseWriter, request *http.Request, timespans [model.TimespanCount]*model.Timespan) error { 
    var session *sessions.Session; 
    var sessionDecodingException error; 
    session, sessionDecodingException = server.SessionStore.Get(request, authenticationSessionName); 
    if sessionDecodingException != nil { 
     return sessionDecodingException; 
    } 


    session.Values[sessionTimestamps] = timespans; 
    return nil; 
} 

func (server *WebServer) getTimespans(request *http.Request) ([model.TimespanCount]*model.Timespan, error) { 
    var session *sessions.Session; 
    var sessionDecodingException error; 
    session, sessionDecodingException = server.SessionStore.Get(request, authenticationSessionName); 
    var readTimespans [model.TimespanCount]*model.Timespan; 
    if sessionDecodingException != nil { 
     return readTimespans, sessionDecodingException; 
    } 

    interfaceValue := reflect.ValueOf(session.Values[sessionTimestamps]); 
    var actuallyAddedTimespan *model.Timespan; 
    for counter := 0; counter < model.TimespanCount; counter++ { 
     actuallyAddedTimespan = &model.Timespan{}; 
     actuallyReflectedTimespan := interfaceValue.Index(counter).Elem(); 
     actuallyAddedTimespan.ID = uint8(actuallyReflectedTimespan.FieldByName("ID").Uint()); 
     //actuallyAddedTimespan.StartDate = actuallyReflectedTimespan.FieldByName("StartDate"); 
     //actuallyAddedTimespan.EndDate = actuallyReflectedTimespan.FieldByName("EndDate"); 
     fmt.Println(actuallyAddedTimespan); 
    } 
    return readTimespans, nil; 
} 
+0

IMHOはJavaと同じように動きます。 – OneOfOne

答えて

2

actuallyAddedTimespan.StartDate = actuallyReflectedTimespan.FieldByName("StartDate").Interface().(time.Time) 

playground

個人的な意見時間が、このためにリフレクションを使用してではなく、シンプルなインターフェイスを使用すると、次のとおりです。

  1. 遅い。
  2. 非効率的
  3. 構造体の外観を変更してリフレクションコードの更新を忘れると、簡単に壊れることがあります。インタフェースを使用しての

例:

func main() { 
    ts := &Timespan{ID: 102, StartDate: time.Now().AddDate(6, 0, 0), EndDate: time.Now().AddDate(8, 0, 0)} 
    m := map[string]interface{}{ 
     "key": ts, 
    } 
    switch v := m["key"].(type) { 
    case Timespaner: 
     fmt.Println(v.Value()) 
    default: 
     fmt.Println("wtfmate?") 
    } 
} 

func (ts *Timespan) Value() (id uint8, start, end time.Time) { 
    return ts.ID, ts.StartDate, ts.EndDate 
} 

type Timespaner interface { 
    Value() (id uint8, start, end time.Time) 
} 

playground

+0

ありがとうございました。しかし、私は本当にあなたが反射の代わりに単純なインターフェイスを使用することによって意味理解していません。あなたがこれを少し説明できるなら、私は最も優雅になるでしょう。 – Lukas

+1

@ルーカスインターフェイスの例を追加しました。これは一般的な考え方ですが、JSON/XMLマーシャリング/アンマーシャリングなどの場合を除き、一般的な考え方は避けてください。 – OneOfOne

+1

インターフェイスの例ありがとうございます。 – Lukas

1

あなたは、構造体からinterface{}値を取得するためにInterface()機能を使用することができます。次にタイプアサーションを使用して正しいタイプを取得することができます。

func main() { 
    t := &Timespan{42, time.Now(), time.Now()} 
    reflectedPointer := reflect.ValueOf(t) 
    reflectedTimespan := reflectedPointer.Elem() 
    var timespan Timespan = reflectedTimespan.Interface().(Timespan) 
    fmt.Println(*t) 
    fmt.Println(timespan) 
}