英文:
How to filter []struct with struct?
问题
我定义了这样的结构体:
type Repo struct {
Key string `json:"key"`
Type string `json:"type"`
PackageType string `json:"packageType"`
}
而 JSON 数据如下所示:
[
{
"key":"docker-sre",
"type":"LOCAL",
"packageType":"Docker"
},
{
"key":"docker-test",
"type":"REMOTE",
"packageType":"Docker"
},
{
"key":"go-local-dev",
"type":"LOCAL",
"packageType":"Go"
},
{
"key":"helm-cloudops",
"type":"LOCAL",
"packageType":"Helm"
}
]
如何以不同的条件获取正确的数据呢?
func getWantedRepos(conf Repo) ([]Repo, error) {}
func main() {
getWantedRepos(Repo{
PackageType: "Docker",
})
getWantedRepos(Repo{
Type: "LOCAL",
PackageType: "Go",
})
}
英文:
I define struct like this:
type Repo struct {
Key string `json:"key"`
Type string `json:"type"`
PackageType string `json:"packageType"`
}
And json data is something like
> [
{
"key":"docker-sre",
"type":"LOCAL",
"packageType":"Docker"
},
{
"key":"docker-test",
"type":"REMOTE",
"packageType":"Docker"
},
{
"key":"go-local-dev",
"type":"LOCAL",
"packageType":"Go"
},
{
"key":"helm-cloudops",
"type":"LOCAL",
"packageType":"Helm"
}
]
What is the best way to get the correct data with different conditions?
func getWantedRepos(conf Repo) ([]Repo, error) {}
func main() {
getWantedRepos(Repo{
PackageType: "Docker",
})
getWantedRepos(Repo{
Type: "LOCAL",
PackageType: "Go",
})
}
答案1
得分: -1
你可以使用内置的reflect
包来实现这个功能。以下是示例代码:
main.go
package main
import (
"fmt"
"reflect"
)
type Repo struct {
Key string `json:"key"`
Type string `json:"type"`
PackageType string `json:"packageType"`
}
var someDatas = []Repo{
{
Key: "test",
Type: "test",
PackageType: "test",
},
{
Key: "test1",
Type: "test1",
PackageType: "test1",
},
{
Key: "test",
Type: "LOCAL",
PackageType: "test23",
},
}
func getWantedRepos(conf map[string]interface{}) []Repo {
var returned []Repo
for _, val := range someDatas {
flag := true
for k := range conf {
if !reflect.DeepEqual(reflect.ValueOf(val).FieldByName(k).Interface(), conf[k]) {
flag = false
break
}
}
if flag {
returned = append(returned, val)
}
}
return returned
}
func main() {
var repos []Repo
repos = getWantedRepos(map[string]interface{}{
"Key": "test",
})
fmt.Println("1 ============================")
fmt.Printf("%+v\n", repos)
repos = getWantedRepos(map[string]interface{}{
"Type": "LOCAL",
})
fmt.Println("2 ============================")
fmt.Printf("%+v\n", repos)
repos = getWantedRepos(map[string]interface{}{
"Type": "LOCAL",
"PackageType": "test23",
})
fmt.Println("3 ============================")
fmt.Printf("%+v\n", repos)
repos = getWantedRepos(map[string]interface{}{
"Type": "LOCAL",
"PackageType": "NONE",
})
fmt.Println("4 ============================")
fmt.Printf("%+v\n", repos)
}
输出结果:
1 ============================
[{Key:test Type:test PackageType:test} {Key:test Type:LOCAL PackageType:test23}]
2 ============================
[{Key:test Type:LOCAL PackageType:test23}]
3 ============================
[{Key:test Type:LOCAL PackageType:test23}]
4 ============================
[]
我使用了map[string]interface{}
而不是模型过滤,因为如果你使用模型,例如带有string
属性的模型,string
的默认值是""。即使你没有初始化属性的值,它也会有""作为默认值,而reflect
循环将扫描并尝试将模型与空字符串""匹配,为了避免这种情况,我使用map[string]interface{}
,这样我们可以更灵活地选择我们想要的属性。
我不知道你有什么测试用例,但如果你从数据库中获取数据,尝试使用WHERE
子句而不是像这样手动过滤。
英文:
You can use reflect
built-in package to do this. This is the example:
main.go
package main
import (
"fmt"
"reflect"
)
type Repo struct {
Key string `json:"key"`
Type string `json:"type"`
PackageType string `json:"packageType"`
}
var someDatas = []Repo{
{
Key: "test",
Type: "test",
PackageType: "test",
},
{
Key: "test1",
Type: "test1",
PackageType: "test1",
},
{
Key: "test",
Type: "LOCAL",
PackageType: "test23",
},
}
func getWantedRepos(conf map[string]interface{}) []Repo {
var returned []Repo
for _, val := range someDatas {
flag := true
for k := range conf {
if !reflect.DeepEqual(reflect.ValueOf(val).FieldByName(k).Interface(), conf[k]) {
flag = false
break
}
}
if flag {
returned = append(returned, val)
}
}
return returned
}
func main() {
var repos []Repo
repos = getWantedRepos(map[string]interface{}{
"Key": "test",
})
fmt.Println("1 ============================")
fmt.Printf("%+v\n", repos)
repos = getWantedRepos(map[string]interface{}{
"Type": "LOCAL",
})
fmt.Println("2 ============================")
fmt.Printf("%+v\n", repos)
repos = getWantedRepos(map[string]interface{}{
"Type": "LOCAL",
"PackageType": "test23",
})
fmt.Println("3 ============================")
fmt.Printf("%+v\n", repos)
repos = getWantedRepos(map[string]interface{}{
"Type": "LOCAL",
"PackageType": "NONE",
})
fmt.Println("4 ============================")
fmt.Printf("%+v\n", repos)
}
Output:
1 ============================
[{Key:test Type:test PackageType:test} {Key:test Type:LOCAL PackageType:test23}]
2 ============================
[{Key:test Type:LOCAL PackageType:test23}]
3 ============================
[{Key:test Type:LOCAL PackageType:test23}]
4 ============================
[]
I use map[string]interface{}
instead of Model filtering because if you use a model, for example with string
attribute, the default value of string
is "". Even if you didn't initialize the value of the attribute, it will have "" as the default value, and the reflect
for loop will scan through and try to match model with empty string "", so to avoid that, I use map[string]interface
so we are more flexible to select attribute we want and vise versa.
I don't know what test case you have, but if you get the datas from database, try to use the WHERE
instead of doing it like this.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论