2017-07-03 96 views
1

當前正在使用Golang中的API Rest。我有這個過程來刪除所有的表格。現在有人要求我根據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 
} 

現在,他可以給我發的全部或部分,在URL字段中,我需要分配一個值,我的結構,以便能夠以搜索該數據庫基於分配給該對象的數據。

我正在使用Gorm處理所有與數據庫,大猩猩/架構分配POST請求和Julien Schmidt路由器上的值。現在,我的問題是:

  1. 我應該在路由中配置什麼來接受動態參數?
  2. 如何將URL中的值分配給類型Media對象? 謝謝!
+0

澄清。你所指的是這些GET參數嗎? – RayfenWindspear

+0

@RayfenWindspear是的,那是符合結構的所有字段。而從客戶端他們可以發送給我一些值來製作過濾器 –

+0

然後你需要的是將'URL.Query()''Values'映射到你的結構體? (https://godoc.org/net/url#URL.Query) – RayfenWindspear

回答

1

您可以使用reflect包遍歷字段並按名稱設置它們。請注意,reflect軟件包使用起來很繁瑣,如果使用不當,還會附帶一些panic的危險。

另外要注意,url.Values.Get只返回第一個值(見https://godoc.org/net/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'包,除非必要,我忍不住要使用它的有趣挑戰。使用它有點像走過「這裏是龍」的領地。 – RayfenWindspear

+1

另一種更容易實現的解決方案是將'json.Marshal'映射到'url.Values'映射,然後'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返回的映射,因爲它爲每個值返回一個數組,並且我只需要該值,而不需要數組。