2017-07-03 429 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返回的映射,因为它为每个值返回一个数组,并且我只需要该值,而不需要数组。