-
-
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
gvar/Scan: When the field is a pointer, it does not take effect #4218
Comments
type SysMenuVo struct {
MenuId int64 `json:"menuId" orm:"menu_id" ` // 菜单ID
MenuName string `json:"menuName" orm:"menu_name" ` // 菜单名称
Children []*SysMenuVo `json:"children" orm:"children"` // 子菜单数
ParentId int64 `json:"parentId" orm:"parent_id" ` // 父菜单ID
OrderNum int `json:"orderNum" orm:"order_num" ` // 显示顺序
Path string `json:"path" orm:"path" ` // 路由地址
Component string `json:"component" orm:"component" ` // 组件路径
QueryParam string `json:"queryParam" orm:"query_param" ` // 路由参数
IsFrame string `json:"isFrame" orm:"is_frame" ` // 是否为外链(0是 1否)
IsCache string `json:"isCache" orm:"is_cache" ` // 是否缓存(0缓存 1不缓存)
MenuType string `json:"menuType" orm:"menu_type" ` // 菜单类型(M目录 C菜单 F按钮)
Visible string `json:"visible" orm:"visible" ` // 显示状态(0显示 1隐藏)
Status string `json:"status" orm:"status" ` // 菜单状态(0正常 1停用)
Perms string `json:"perms" orm:"perms" ` // 权限标识
Icon string `json:"icon" orm:"icon" ` // 菜单图标
// CreateDept int64 `json:"createDept" orm:"create_dept" ` // 创建部门
// CreateBy int64 `json:"createBy" orm:"create_by" ` // 创建者
CreateTime *gtime.Time `json:"createTime" orm:"create_time" ` // 创建时间
// UpdateBy int64 `json:"updateBy" orm:"update_by" ` // 更新者
// UpdateTime *gtime.Time `json:"updateTime" orm:"update_time" ` // 更新时间
Remark string `json:"remark" orm:"remark" ` // 备注
} |
以下是最小可运行代码 package main
import (
"fmt"
"github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/util/gconv"
)
func main() {
menus := []*SysMenuVo{
{
MenuId: 1,
MenuName: "系统管理",
ParentId: 0,
},
{
MenuId: 2,
MenuName: "字典查询",
ParentId: 1,
},
}
var menuVoList = make([]*SysMenuVo, 0)
for _, v := range menus {
var vo *SysMenuVo
gconv.Struct(v, &vo)
vo.MenuId = v.MenuId
menuVoList = append(menuVoList, vo)
}
root := BuildMenuTree(menuVoList)
g.Dump(root)
}
// 辅助函数,用于将映射转换为树结构
func BuildMenuTree(routes []*SysMenuVo) (roots []*SysMenuVo) {
var tree = BuildMenuMap(routes)
for _, key := range tree.Keys() {
var node *SysMenuVo
nodeSysMenu := tree.GetVar(key)
nodeSysMenu.Scan(&node)
if node.ParentId == 0 {
roots = append(roots, node)
} else {
var parent *SysMenuVo
nodeParent := tree.GetVar(node.ParentId)
nodeParent.Scan(&parent)
fmt.Printf("parent.children=%p,%p\n", &parent.Children, &roots[0].Children)
// parent := tree[node.ParentId]
if parent != nil {
if g.IsEmpty(parent.Children) {
parent.Children = make([]*SysMenuVo, 0)
}
parent.Children = append(parent.Children, node)
fmt.Println()
}
}
}
if len(roots) == 0 {
return roots
}
return roots
}
// 构建树的函数
func BuildMenuMap(routes []*SysMenuVo) *gmap.ListMap {
tree := gmap.NewListMap()
for i := range routes {
var res *SysMenuVo
var item = routes[i]
gconv.Scan(item, &res)
// tree[item.MenuId] = res
tree.Set(item.MenuId, res)
}
return tree
}
type SysMenuVo struct {
MenuId int64 `json:"menuId" orm:"menu_id" ` // 菜单ID
MenuName string `json:"menuName" orm:"menu_name" ` // 菜单名称
Children []*SysMenuVo `json:"children" orm:"children"` // 子菜单数
ParentId int64 `json:"parentId" orm:"parent_id" ` // 父菜单ID
} 这个是2.8.3 的代码 两次运行结果不一致 |
@806572349 @gqcn 在2.8.3中,&parent.Children和&roots[0].Children两者地址一致,你在向parent.Children中添加时,其实就是在向roots[0].Children添加,2.9.0,两者地址不一致,所以在parent.Children中添加,roots[0].Children并不会更新,具体可以运行代码,看BuildMenuTree函数里面的打印即可 |
@806572349 @gqcn In 2.8.3, the addresses of &parent.Children and &roots[0].Children are the same. When you add to parent.Children, you are actually adding to roots[0].Children, 2.9.0. The addresses of the two are inconsistent, so when adding to parent.Children, roots[0].Children will not be updated. |
|
|
最小化复现代码: package main
import (
"fmt"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv"
)
type SysMenuVo struct {
MenuId int64 `json:"menuId" orm:"menu_id" ` // 菜单ID
MenuName string `json:"menuName" orm:"menu_name" ` // 菜单名称
Children []*SysMenuVo `json:"children" orm:"children"` // 子菜单数
ParentId int64 `json:"parentId" orm:"parent_id" ` // 父菜单ID
}
func main() {
menus := []*SysMenuVo{
{
MenuId: 1,
MenuName: "系统管理",
ParentId: 0,
},
{
MenuId: 2,
MenuName: "字典查询",
ParentId: 1,
},
}
var parent *SysMenuVo
err := gconv.Scan(menus[0], &parent)
if err != nil {
panic(err)
}
fmt.Printf("parent.children=%p,%p\n", &parent.Children, &menus[0].Children)
parent.Children = append(parent.Children, menus[1])
g.Dump(menus)
} |
@gqcn 应在文档或注释中说明当类型相同时,转换的逻辑,根据目前支持的参数类型,可以分为以下
第1 2种情况只能是值赋值,修改dst时,不会影响src,所以children=nil 综上,前3种情况的转换,children=nil,只有第4种children!=nil 还有,也需要补充对于字段类型相同时,如果是指针类型,需说明是值赋值,还是指针赋值 |
@gqcn should be explained in the document or comments when the type is the same, the logic of the conversion can be divided into the following according to the currently supported parameter types.
The 1st and 2nd case can only be value assignment. When modifying dst, src will not affect src, so children=nil In summary, children=nil for the first three situations, only the fourth child!=nil Also, it is also necessary to add that if the field type is the same, if it is a pointer type, it is necessary to specify whether it is a value assignment or a pointer assignment. |
Go version
1.24.1 linxu
GoFrame version
2.9.0
Can this bug be reproduced with the latest release?
Option Yes
What did you do?
2.8.3 则没有这个问题
What did you see happen?
这个是2.9.0升级过的后,children 指针没有返回。tree.GetVar(node.ParentId).scan(&parent)
What did you expect to see?
希望可以恢复到2.8.3的情况
The text was updated successfully, but these errors were encountered: