2017-07-03 13 views
1

現在、GolangのAPI Restで作業しています。私はすべてのテーブルをCRUDするプロセスを持っています。ここで誰かがURLに送信するパラメータに基づいてそのテーブルの1つを検索するエンドポイントを開発するように求めています。 URL内のフィールド彼は私のすべて、またはその一部を送信することができ、GolangのURLの動的パラメータを処理します。

type Media struct { 
    ID       uint  
    Key     string  
    RecordKey   string  
    RecordID   string  
    SystemMediaKey  string   
    MediaObjectID  string 
    ChangedByID   string 
    ChangedByKey  string 
    MediaCategory    string 
    MimeType     string 
    ShortDescription   string 
    LongDescription   string 
    EntryTimestamp    time.Time 
    ModificationTimestamp  time.Time 
    DeletedAtTimestamp   *time.Time 
    MediaModificationTimestamp time.Time 
    MediaURL     string 
    MediaHTML     string 
    Order      int  
    Group      string 
    Width      int  
    Height      int  
    ImageSize     string 
    ResourceName    string 
    ClassName     string 
    Permission     *string 
    MediaStatus    string 
} 

、私は私の構造体に値がで検索できるようにすることを割り当てる必要がありますのは、これがそのテーブルの私の構造体であることを言ってみましょうオブジェクトに割り当てられたデータに基づいてデータベースを更新します。

私はGormを使って、データベースとgorilla/schemaのすべてを処理し、POST要求とJulien Schmidt Routerの値を割り当てています。さて、私の質問は次の通りです:

  1. 動的パラメータを受け入れるための経路はどうすればよいですか?
  2. URLに含まれる値をメディアオブジェクトに割り当てるにはどうしたらいいですか? ありがとうございました!
+0

明確化。あなたが参照しているこれらのGETパラメータはありますか? – RayfenWindspear

+0

@RayfenWindspearはい、それは構造体に適合するすべてのフィールドです。そしてクライアント側からは、フィルタを作るために値を持つものを私に送ることができます。 –

+0

'URL.Query()' Values'を構造体にマップするだけです。 (https://godoc.org/net/url#URL.Query) – RayfenWindspear

答えて

1

reflectパッケージを使用して、フィールドを反復処理し、名前で設定できます。 reflectパッケージは使用するのが難しく、正しく使用されない場合はpanicの危険性があることに注意してください。

また

EDIT(詳細はhttps://godoc.org/net/url#Values.Getを参照)url.Values.Getは最初の値だけを返すことに注意してください:私は、構造体のポインタを説明するためにコードを追加しました。彼らは異なって扱われます。

https://play.golang.org/p/AO4lYx7xka

package main 

import (
    "fmt" 
    "net/url" 
    "reflect" 
    "time" 
) 

type Media struct { 
    ID       uint 
    Key      string 
    RecordKey     string 
    RecordID     string 
    SystemMediaKey    string 
    MediaObjectID    string 
    ChangedByID    string 
    ChangedByKey    string 
    MediaCategory    string 
    MimeType     string 
    ShortDescription   string 
    LongDescription   string 
    EntryTimestamp    time.Time 
    ModificationTimestamp  time.Time 
    DeletedAtTimestamp   *time.Time 
    MediaModificationTimestamp time.Time 
    MediaURL     string 
    MediaHTML     string 
    Order      int 
    Group      string 
    Width      int 
    Height      int 
    ImageSize     string 
    ResourceName    string 
    ClassName     string 
    Permission     *string 
    MediaStatus    string 
} 

func main() { 

    testUrl := "www.example.com/test?MimeType=themimetype&Key=thekey&Permission=admin" 

    u, err := url.Parse(testUrl) 
    if err != nil { 
     fmt.Println(err) 
     return 
    } 

    params := u.Query() 

    media := &Media{} 

    val := reflect.ValueOf(media) 

    for i := 0; i < val.Elem().NumField(); i++ { 
     // get the reflect.StructField so we can get the Name 
     f := val.Elem().Type().Field(i) 

     // check if URL.Values contains the field 
     if v := params.Get(f.Name); v != "" { 
      // get the reflect.Value associated with the Field 
      field := val.Elem().FieldByName(f.Name) 

      kind := field.Kind() 

      // you must switch for each reflect.Kind (associated with the type in your struct) 
      // so you know which Set... method to call 
      switch kind { 
      case reflect.String: 
       field.SetString(v) 
      case reflect.Ptr: 
       // pointers are a special case that must be handled manually unfortunately. 
       // because they default to nil, calling Elem() won't reveal the underlying type 
       // so you must simply string match the struct values that are pointers. 
       switch f.Name { 
       case "Permission": 
        newVal := reflect.New(reflect.TypeOf(v)) 
        newVal.Elem().SetString(v) 
        field.Set(newVal.Elem().Addr()) 
       case "DeletedAtTimestamp": 
       } 
      } 

     } 
    } 

    fmt.Printf("%#v\n", media) 
    fmt.Println(*media.Permission) 
} 
+0

私は、必要がない限り、 'reflect'パッケージを使用することを厳密に主張していませんが、私はそれを使うのに面白い挑戦に抵抗することはできません。それを使って、 "here be dragons"の領域を歩く。 – RayfenWindspear

+1

実装が簡単なもう一つの解決策は、 'url.Values'マップを' json.Marshal'にし、 'json.Unmarshal'をあなたの構造体に戻すことです。このメソッドは実際に実装するのが簡単かもしれませんが、JSONエンコーダー/デコーダーはかなり大きく、効率が低い傾向があります。 'url.Values'は' map [string] [] string'なので、単純ではないかもしれません。そのため、値を配列としてマーシャリングします。これは、私が直接どのように動作するのか(そしてそれがどうなるのか)頭の上を知っていたので、 'reflect'パッケージを使って直接選択した理由です。 – RayfenWindspear

+0

ようやく私はこのライブラリを使用してhttp://godoc.org/github.com/mitchellh/mapstructure#Decodeを見つけたので、それは仕事になります –

0

私は最終的に構造体へのマップに変換this libraryを使用することができました。唯一のことは、URL.Query() Valuesによって返されるマップを前処理しなければならなかったことです。なぜなら、各値の配列を返し、配列内ではなく値しか必要としないからです。

関連する問題