-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
perf(util/gconv): improve performance for struct converting #3412
Conversation
@wln732 The ci fails. |
涉及到核心转换逻辑调整,需要花点时间 |
When it comes to adjusting the core conversion logic, it will take some time to |
@wln32 有冲突了,更新pr呢,我继续review。 |
@wln32 There is a conflict. I have updated the PR and I will continue the review. |
# Conflicts: # util/gconv/gconv_struct.go
@gqcn 有一个测试跑不过了,#3429 这个pr中修改了 type StructFromIssue1227 struct {
Name string `json:"中文Key"`
}
tests := []struct {
name string
origin interface{}
want string
}
for _, tt := range tests {
p := StructFromIssue1227{}
if err := gconv.Struct(tt.origin, &p); err != nil {
t.Error(err)
}
t.Assert(p.Name, tt.want)
}
// 之前的,可以匹配到中文KEY
{
name: "Case5",
origin: g.Map{"中文KEY": "n1"},
want: "n1",
}
// 修改后的,匹配不到中文KEY
{
name: "Case5",
origin: g.Map{"中文KEY": "n1"},
want: "",
} 按照文档的匹配规则来说,忽略下划线特殊符号大小写之类的,不是应该可以匹配到吗? |
新版本调整了其中一个 |
@wln32 The CI failed. |
@gqcn 强哥 目前gconv有行为不一致和字段多次赋值的情况 1.目前gconv.Struct行为不一致情况例如以下代码 type ObjectMeta struct {
Name string `json:"name"`
}
type ConfigMap struct {
ObjectMeta `json:"metadata" `
TypeMeta string `json:",inline"`
Immutable bool `json:"immutable" `
}
jsonStringData := `{
"name": "test",
"TypeMeta": "j",
"immutable": false
}
`
var cfg2 ConfigMap
// 从字符串转换到结构体
err = gconv.Struct(jsonStringData, &cfg2)
if err != nil {
panic(err)
}
g.Dump(cfg2)
// 反序列化结果
{
Name: "",
TypeMeta: "j",
Immutable: false,
}
//=========================================
如果data是一个map时,结果和上面的不一样
data := g.Map{
"name": "test",
"TypeMeta": "j",
"immutable": false,
}
var cfg3 ConfigMap
err = gconv.Struct(data, &cfg3)
if err != nil {
panic(err)
}
g.Dump(cfg3)
// 结果
{
Name: "test",
TypeMeta: "j",
Immutable: false,
} 如果将ObjectMeta的json tag去掉,则结果输出一致 造成这一差异的情况的原因是,当从字符串转换到结构体时 需要这样才能匹配到name
"metadata":{
"name":"test"
}, 2.目前gconv.Struct对匿名结构体字段多次赋值这种情况发生在从map转换到strcut时 以这个结构体作为例子 type ObjectMeta struct {
Name string `json:"name"`
}
type ConfigMap struct {
ObjectMeta // `json:"metadata" `
TypeMeta string `json:",inline"`
Immutable bool `json:"immutable" `
} 1.开始循环 ①识别到匿名字段ObjectMeta,并进入递归处理,会 2.处理带有tag的结构体字段gstructs.TagMapName这个方法会把所有字段都解析出来,包括匿名结构体的字段 如果ObjectMeta这种的匿名结构体带有json tag时,这个字段也会被解析。 3.开始赋值根据用户自定义的映射规则赋值,略过 根据用户定义的tag来赋值,就是根据 根据字段名赋值,略过 如果嵌套的结构体字段数量比较多的话,非常影响效率 |
@gqcn Brother Qiang currently has inconsistent behavior and multiple field assignments in gconv. 1. The current behavior of gconv.Struct is inconsistentFor example the following code typeObjectMeta struct {
Name string `json:"name"`
}
type ConfigMap struct {
ObjectMeta `json:" metadata" `
TypeMeta string `json:",inline"`
Immutable bool `json:" immutable" `
}
jsonStringData := `{
"name": "test",
"TypeMeta": "j",
"immutable": false
}
`
var cfg2 ConfigMap
//Convert from string to structure
err = gconv.Struct(jsonStringData, &cfg2)
if err != nil {
panic(err)
}
g.Dump(cfg2)
//Deserialize results
{
Name: "",
TypeMeta: "j",
Immutable: false,
}
//==========================================
If data is a map, the result is different from the above
data := g.Map{
"name": "test",
"TypeMeta": "j",
"immutable": false,
}
var cfg3 ConfigMap
err = gconv.Struct(data, &cfg3)
if err != nil {
panic(err)
}
g.Dump(cfg3)
// result
{
Name: "test",
TypeMeta: "j",
Immutable: false,
} If the json tag of ObjectMeta is removed, the result output will be consistent. The reason for this discrepancy is that when converting from string to struct This is needed to match the name
"metadata":{
"name":"test"
}, 2. Currently gconv.Struct assigns multiple values to anonymous structure fields.This happens when converting from map to strcut Take this structure as an example typeObjectMeta struct {
Name string `json:"name"`
}
type ConfigMap struct {
ObjectMeta // `json:" metadata" `
TypeMeta string `json:",inline"`
Immutable bool `json:" immutable" `
} 1. Start looping① Recognize the anonymous field ObjectMeta and enter recursive processing. It will 2. Process structure fields with tagsThe gstructs.TagMapName method will parse out all fields, including fields of anonymous structures. If an anonymous structure such as ObjectMeta has a json tag, this field will also be parsed. 3. Start assignmentAssign values according to user-defined mapping rules, skip Assigning values based on user-defined tags means assigning values based on Assign values based on field names, skip If the number of nested structure fields is relatively large, it will greatly affect the efficiency. |
截至目前最新提交的性能大幅度提升