Golang实现中树形结构值丢失问题探讨

Golang实现中树形结构值丢失问题探讨

package main

import (
	"encoding/json"
	"fmt"
)

type employee struct {
	Name      string      `json:"name"`
	Id        int         `json:"id,omitempty"`
	ManagerId int         `json:"managerid"`
	Reporters []employee `json:"reporters,omitempty"`
}

// type employees struct {
// 	employees []employee `json:"employee"`
// }

type EmployeeList struct {
	employees map[int]employee
	root  employee
}

func NewEmployeeList() *EmployeeList {
	var el EmployeeList
	el.employees = make(map[int]employee)
	return &el
}


func (el EmployeeList) CreateMap(employeesInfo []employee) {	 
	for _ , emp := range employeesInfo {
		e := employee{
			Name : emp.Name,
			Id: emp.Id,
			ManagerId: emp.ManagerId,
		}
		el.employees[emp.Id] = e
		if(emp.ManagerId == 0){
			el.root = e
			fmt.Println("CreateMap",el.root)
		}
	}
	fmt.Println("CreateMap2",el.root,el.employees)
}

func (el EmployeeList) getReportersById(empId int) []employee {	 
	reporters := []employee{}
	for _ , employee := range el.employees {
		if(employee.ManagerId == empId){
			reporters = append(reporters, employee)
		}
	}
	return reporters
}

func (el EmployeeList) maketree(e employee) {	 
	//e := root
	e.Reporters = el.getReportersById(e.Id)
	if(true){
		fmt.Println("maketree",e.Id,e.Name,e.Reporters)
	}
	// e.Reporters = reporters
	if(len(e.Reporters) == 0){
		return
	}
	for _ , reporterEmployee := range e.Reporters {
		el.maketree(reporterEmployee);
	}
}

func (el EmployeeList) print(root employee, level int) {	 
	for i:= 0; i<level;i++ {
		fmt.Print("\t");
	}
	fmt.Println(root.Name);
	for _, reporter := range root.Reporters {
		fmt.Println("Enter");
		el.print(reporter, level + 1)
	}
}

func main() {
	//1. Read JSON File
	myJsonString := `[{    "name": "Rob",    "id": 7,    "managerid": 3 }, {    "name": "Rex",    "id": 6,    "managerid": 2 }, {    "name": "Jake",    "id": 5,    "managerid": 2 }, {    "name": "Paul",    "id": 4,    "managerid": 1 }, {    "name": "Oliver",    "id": 3,    "managerid": 1 }, {    "name": "John",    "id": 2,    "managerid": 1 }, {    "name": "Britney",    "id": 1,    "managerid": 0 }]`
	//2. Create class and sent file data
	emplist := NewEmployeeList()
	rawEmployeesInfo := []employee{}
	
	_ = json.Unmarshal([]byte(myJsonString),&rawEmployeesInfo);
	fmt.Println(rawEmployeesInfo);
	emplist.CreateMap(rawEmployeesInfo);
	//fmt.Println(emplist.employees,emplist.root);
	fmt.Println("Main1",emplist.root)
	emplist.maketree(emplist.root);
	//fmt.Println(emplist.root)
	fmt.Println("Main2",emplist.root)
	emplist.print(emplist.root,0)
}

运行代码时,在打印树的内容之前,树的值丢失了。有人能告诉我哪里出错了吗?


更多关于Golang实现中树形结构值丢失问题探讨的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

你传递的是 el*EmployeeList 作为值接收器。这意味着 Go 会创建一个本地副本,并在该副本上进行修改。

只需将其更改为指针接收器即可解决问题:

func (el *EmployeeList) CreateMap(employeesInfo []employee) {…

更多关于Golang实现中树形结构值丢失问题探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


CreateMapmaketree方法中,您使用了值接收器,这会导致结构体副本被修改,而不是原始对象。以下是修正后的代码:

package main

import (
	"encoding/json"
	"fmt"
)

type employee struct {
	Name      string      `json:"name"`
	Id        int         `json:"id,omitempty"`
	ManagerId int         `json:"managerid"`
	Reporters []employee `json:"reporters,omitempty"`
}

type EmployeeList struct {
	employees map[int]employee
	root      employee
}

func NewEmployeeList() *EmployeeList {
	var el EmployeeList
	el.employees = make(map[int]employee)
	return &el
}

// 改为指针接收器
func (el *EmployeeList) CreateMap(employeesInfo []employee) {
	for _, emp := range employeesInfo {
		e := employee{
			Name:      emp.Name,
			Id:        emp.Id,
			ManagerId: emp.ManagerId,
		}
		el.employees[emp.Id] = e
		if emp.ManagerId == 0 {
			el.root = e
			fmt.Println("CreateMap", el.root)
		}
	}
	fmt.Println("CreateMap2", el.root, el.employees)
}

func (el *EmployeeList) getReportersById(empId int) []employee {
	reporters := []employee{}
	for _, employee := range el.employees {
		if employee.ManagerId == empId {
			reporters = append(reporters, employee)
		}
	}
	return reporters
}

// 改为指针接收器,并修改为直接操作map中的employee
func (el *EmployeeList) maketree(empId int) {
	emp := el.employees[empId]
	emp.Reporters = el.getReportersById(empId)
	
	// 更新map中的employee
	el.employees[empId] = emp
	
	fmt.Println("maketree", emp.Id, emp.Name, emp.Reporters)
	
	if len(emp.Reporters) == 0 {
		return
	}
	
	for _, reporter := range emp.Reporters {
		el.maketree(reporter.Id)
	}
}

func (el *EmployeeList) print(root employee, level int) {
	for i := 0; i < level; i++ {
		fmt.Print("\t")
	}
	fmt.Println(root.Name)
	for _, reporter := range root.Reporters {
		el.print(reporter, level+1)
	}
}

func main() {
	myJsonString := `[{    "name": "Rob",    "id": 7,    "managerid": 3 }, {    "name": "Rex",    "id": 6,    "managerid": 2 }, {    "name": "Jake",    "id": 5,    "managerid": 2 }, {    "name": "Paul",    "id": 4,    "managerid": 1 }, {    "name": "Oliver",    "id": 3,    "managerid": 1 }, {    "name": "John",    "id": 2,    "managerid": 1 }, {    "name": "Britney",    "id": 1,    "managerid": 0 }]`
	
	emplist := NewEmployeeList()
	rawEmployeesInfo := []employee{}
	
	_ = json.Unmarshal([]byte(myJsonString), &rawEmployeesInfo)
	fmt.Println(rawEmployeesInfo)
	
	emplist.CreateMap(rawEmployeesInfo)
	fmt.Println("Main1", emplist.root)
	
	// 从根节点开始构建树
	emplist.maketree(emplist.root.Id)
	
	// 更新根节点
	emplist.root = emplist.employees[emplist.root.Id]
	
	fmt.Println("Main2", emplist.root)
	emplist.print(emplist.root, 0)
}

主要修改:

  1. CreateMapgetReportersByIdmaketreeprint方法的接收器改为指针类型(*EmployeeList
  2. 修改maketree方法,直接操作el.employeesmap中的employee对象
  3. main函数中,构建树后更新根节点引用

这样修改后,树形结构的值就不会丢失了。

回到顶部