如何循环遍历结构体的字段以进行查询过滤。

huangapple go评论108阅读模式
英文:

how to loop over fields of a struct for query filtering

问题

我有一个数据库,每一行对应一个具有以下字段的结构体:

type item struct {
    ItemId *string `json:"item_id"`
    OwnerId *string `json:"owner_id"`
    Status *string `json:"status"`
    ... // 还有很多其他字段
}

在数据库中,所有行的所有字段都已填充。现在我想要一个函数,它以可能未填充字段的item对象作为输入,并返回一个SQL查询字符串。例如:

func FindItems(filter item) string

输入的item用作过滤器。逻辑如下(类似于Python风格):

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

在Go中如何实现这个功能?或者在Go中有更好的过滤方法吗?

英文:

I have a database where each row corresponds to a struct with the following fields

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

Inside the database, all fields are filled for all rows. Now I would like to have a function that takes an item object whose fields may not be filled as input and return a SQL query string. For example

func FindItems(filter item) string

The input item serves as a filter. The logic is as follows (in kind of python style)

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

How can I do this in go? Or is there a better way to do filter in go?

答案1

得分: 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字段的名称。

英文:

You can use reflect package to enumerate your structure fields and values:

<!-- language: go -->

package main

import (
    &quot;fmt&quot;
    &quot;reflect&quot;
)

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

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

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

Keep in mind that using additional json tags like json:&quot;item_id,omitempty&quot; will break your query. You should consider using custom structure tags to define the names of SQL fields.

huangapple
  • 本文由 发表于 2016年12月4日 23:42:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/40960350.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定