2016-12-04 25 views
1

有每行对应于一个结构具有以下字段我如何循环struct的字段查询过滤

type item struct { 
    ItemId *string `json:"item_id"` 
    OwnerId *string `json:"owner_id"` 
    Status *string `json:"status"` 
    ... // many more 
} 

数据库在数据库中,填写了所有字段的所有行。现在我想要一个函数,它需要一个item对象,它的字段可能不会被填充为输入并返回一个SQL查询字符串。例如,

func FindItems(filter item) string 

输入item充当过滤器。逻辑如下(以蟒蛇风格的种类)

query = `select * from item_table` 
condition = "" 
for field, value in filter: 
    if value != nil: 
     condition = " and " if condition else " where " 
     condition += " field=value" 
query += condition 

我该怎么办呢?或者是否有更好的方法来进行过滤?

+0

[Go:从接口获取所有字段]的可能重复(http://stackoverflow.com/questions/39866503/go-get-all-fields-from-an-interface/39866671#39866671)。 – icza

回答

2

您可以使用reflect包枚举您的结构域和值:

package main 

import (
    "fmt" 
    "reflect" 
) 

type item struct { 
    ItemID *string `json:"item_id"` 
    OwnerID *string `json:"owner_id"` 
    Status *string `json:"status"` 
} 

func FindItemsQuery(filter item) string { 
    query := `select * from item_table` 
    condition := "" 
    val := reflect.ValueOf(filter) 
    for i := 0; i < val.NumField(); i++ { 
     valField := val.Field(i) 
     if !valField.IsNil() { 
      if condition != "" { 
       condition += " and " 
      } else { 
       condition += " where " 
      } 
      condition += fmt.Sprintf("%s=%v", val.Type().Field(i).Tag.Get("json"), valField.Elem()) 
     } 
    } 
    return query + condition 
} 

func main() { 
    itemID := "123" 
    item := item{ItemID: &itemID} 
    fmt.Println(FindItemsQuery(item)) // select * from item_table where item_id=123 
} 

请记住,通过另外的JSON标签,如json:"item_id,omitempty"将打破您的查询。您应该考虑使用自定义结构标记来定义SQL字段的名称。

+0

为什么你需要'valField.Elem().interface()'而不是'valField.Elem()'? – nos

+0

@nos我没有意识到'fmt.Sprintf'能够处理'reflect.Value'类型,你是对的。 – KAdot