Recursion function on a struct in Golang - recursion

I have the following code to organise *Widget structs into a hierarchy. Parent() returns the widget with an ID of the caller's parentID. The hierarchy can be up to 4 or 5 levels deep.
type Widget struct {
ID int64
ParentID int64
}
func (w *Widget) Parent() *Widget {
// Returns the widget with an ID of w.ParentID
}
What I want to achieve is a function which aggregates the parent, as well as the parent's parent etc. to the top of the hierarchy, and returns a slice of all of the parent IDs. As I don't know the depth of the hierarchy, I think I need some sort of programmatic recursion to get the parent of each parent, which would do something like the following:
func (w *Widget) AllParents() []*Widget {
var parentWidgets []*Widget
x := w.Parent()
parentWidgets = append(parentWidgets, x)
y := x.Parent()
parentWidgets = append(parentWidgets, y)
...
return parentWidgets
}
Is there a more idiomatic way of achieving this?

You just need to step higher and higher in the hierarchy until you reach the root. Assuming Widget.Parent() returns nil if the Widget is the "root" (meaning it has no parent):
Iterative solution
Here is the solution with a simple for loop:
func (w *Widget) AllParents() []*Widget {
var ws []*Widget
for parent := w.Parent(); parent != nil; parent = parent.Parent() {
ws = append(ws, parent)
}
return ws
}
This method will return nil if called on the "root" (zero value for all slice types). In other cases, it will return the "path" from the direct parent leading to the "root".
Here's a little test program. It creates a root widget with ID = 0, a child with ID = 1 and a "grandchild" with ID = 2, and prints AllParents() called on each. To implement Widget.Parent(), I used a simple "widget registry" map.
Result as expected:
Parents of 0:
Parents of 1: 0
Parents of 2: 1 0
Try it on the Go Playground.
var wreg = map[int64]*Widget{}
func (w *Widget) Parent() *Widget {
// Returns the widget with an ID of w.ParentID
return wreg[w.ParentID]
}
func main() {
w := &Widget{0, -1}
wreg[w.ID] = w
w2 := &Widget{1, 0}
wreg[w2.ID] = w2
w3 := &Widget{2, 1}
wreg[w3.ID] = w3
printParents(w)
printParents(w2)
printParents(w3)
}
func printParents(w *Widget) {
fmt.Printf("Parents of %d:", w.ID)
for _, w := range w.AllParents() {
fmt.Print(" ", w.ID)
}
fmt.Println()
}
Recursive solution
Of course it can be solved using recursion too:
func (w *Widget) AllParents() []*Widget {
if parent := w.Parent(); parent == nil {
return nil
} else {
return append(parent.AllParents(), parent)
}
}
This solution returns the "path" from the root leading to the direct parent.
Running the above test program with this implementation, output is:
Parents of 0:
Parents of 1: 0
Parents of 2: 0 1
Try this on the Go Playground.

Related

How to create a new struct and use its original value as a member of the new struct

I am trying to create a new struct and use its original value as a member of the new struct. However, they both end up being the same reference (i.e. payload and payload.prev) and it causes infinite recursion in my code. I appreciate any help or hint.
package main
type Sieve struct {
prime int
prev *Sieve
}
func Test(payload *Sieve, n int) {
if payload.prime*(n/payload.prime) == n {
} else if payload.prev == nil {
println(n)
// payload and payload.prev end up being the same reference
// and it causes infinite loop
*payload = Sieve{
prime: n,
prev: payload,
}
} else {
Test(payload.prev, n)
}
}
func main() {
var p = Sieve{
prev: nil,
prime: 2,
}
println(2)
for i := 2; i < 10; i++ {
Test(&p, i)
}
}
You want to update the "payload" pointer to point to the address of a new struct. Construct your new struct like this:
payload = &Sieve{
prime: n,
prev: payload,
}
Before overwriting the Sieve struct pointed by payload make a copy of it:
p := *payload
And now you can assign a new Sieve struct value, storing the address of the copy as its prev field:
*payload = Sieve{
prime: n,
prev: &p,
}
With this change, your app runs and properly outputs the primes between 2 and 10 (try it on the Go Playground):
2
3
5
7
With this code below, you are not creating a new instance of Sieve, you are setting the existing instance of Sieve to point to itself:
*payload = Sieve{
prime: n,
prev: payload,
}
If you want to push the payload one level down, you can do this:
p:=*payload
*payload = Sieve {
prime: n,
prev: &p}
This will first assign the contents of payload to p, and then will rewrite payload contents to point to p.
On the other hand, if you want to create a new payload pointing to the old one, use:
payload = Sieve {
prime: n,
prev: payload }
Then you have to return/use this new payload pointer.

Golang struct pointer reference lost when calling struct property method

I'm attempting to use a struct to manage accessing nodes on a tree. Whenever I access the method of the parent's child node, the parent reference on the subsequent call gets lost (i.e. parent.child.method(child) -> [parent becomes nil]-> parent(the previous child).child ... etc).
Here is the error snippet from my file.
type Node struct {
Left *Node
Right *Node
value int
}
func (parent *Node) determineSide(child *Node) (Node, Node) {
if child.Value < parent.Value {
if parent.hasLeftNode() {
return parent.Left.determineSide(child)
}
return parent.addLeftNode(child)
} else if child.Value > parent.Value {
if parent.hasRightNode() {
return parent.Right.determineSide(child)
}
return parent.addRightNode(child)
}
return *child, *parent
}
I attempted to solve this by trying to find a way to inform the method that the new reference should be parent.Left. Things like using *parent.Left and &parent.Left didn't seem to be correct.
A solution may might be to move this code outside of the struct and have another function handle the outcome for a quick fix, but I'd like to understand why this isn't working out of the box. Thought process here is influenced by using this.child.determineSide(child).
Full code is here.
Edit
Here is some output from the terminal that might give even further context. Looks like I'm having a check type issue leading to the problem.
parent &{<nil> <nil> 2}
parent.Left <nil>
parent.LeftNode true
child &{<nil> <nil> 1}
parent <nil>
child &{<nil> <nil> 1}
Okay, I know what u'r exactly asking finally.
New() methods returns a value, not a pointer, which means u can't see later change in caller. What the caller got is only a value copy of the Node. So the parent what u print will always be {Left:<nil> Right:<nil> Value:2}.
So the same with addLeftNode() and addRightNode().
Just use pointer, not value to achieve your goal.
See pointers_vs_values
I think it's just the Visit() method where the problem is.
It will never visit right child when u immediately return after visited left child.
The left and right child are not mutually exclusive, so the second if-clause should not use else if, which would be if.
The visiting order also has problem.
Before:
// Visit will automatically walk through the Child Nodes of the accessed Parent Node.
func (parent *Node) Visit() (Node, int) {
fmt.Println("Node value:", parent.Value)
if parent.hasLeftNode() {
return parent.Left.Visit()
} else if parent.hasRightNode() {
return parent.Right.Visit()
}
return *parent, parent.Value
}
Modified:
// Visit will automatically walk through the Child Nodes of the accessed Parent Node.
func (parent *Node) Visit() (Node, int) {
if parent.hasLeftNode() {
parent.Left.Visit()
}
fmt.Println("Node value:", parent.Value)
if parent.hasRightNode() {
parent.Right.Visit()
}
return *parent, parent.Value
}
Additionally, as to me, Visit() shouldn't return any values.
Problem originated from incorrect type checking. The function successfully handled the call, but the method I was using wasn't accurate in confirming whether a node was assigned.
// isNode checks whether the provided property is a Node.
func (parent *Node) isNode(property interface{}, typeset interface{}) bool {
fmt.Println(reflect.TypeOf(property) == reflect.TypeOf(typeset))
// this always referred to the address for the base Node struct or similar falsy.
return reflect.TypeOf(property) == reflect.TypeOf(typeset)
}
// hasLeftSide tests whether the Parent Node has a Node assigned to its left side.
func (parent *Node) hasLeftNode() bool {
return parent.Left != nil //parent.isNode(parent.Left, (*Node)(nil))
}
// hasRightSide tests whether the Parent Node has a Node assigned to its right side.
func (parent *Node) hasRightNode() bool {
return parent.Right != nil // parent.isNode(parent.Right, (*Node)(nil))
}

golang - how to initialize a map field within a struct?

I'm confused about the best way to initialize a struct that contains a map. Running this code produces panic: runtime error: assignment to entry in nil map:
package main
type Vertex struct {
label string
}
type Graph struct {
connections map[Vertex][]Vertex
}
func main() {
v1 := Vertex{"v1"}
v2 := Vertex{"v2"}
g := new(Graph)
g.connections[v1] = append(g.coonections[v1], v2)
g.connections[v2] = append(g.connections[v2], v1)
}
One idea is to create a constructor, as in this answer.
Another idea is to use an add_connection method that can initialize the map if it's empty:
func (g *Graph) add_connection(v1, v2 Vertex) {
if g.connections == nil {
g.connections = make(map[Vertex][]Vertex)
}
g.connections[v1] = append(g.connections[v1], v2)
g.connections[v2] = append(g.connections[v2], v1)
}
Are there other options? Just wanted to see if there is a commonly-accepted way to do this.
I would probably use a constructor to do this:
func NewGraph() *Graph {
var g Graph
g.connections = make(map[Vertex][]Vertex)
return &g
}
I've found this example in the standard image/jpeg package (not with a map though, but with a slice):
type Alpha struct {
Pix []uint8
Stride int
Rect Rectangle
}
func NewAlpha(r Rectangle) *Alpha {
w, h := r.Dx(), r.Dy()
pix := make([]uint8, 1*w*h)
return &Alpha{pix, 1 * w, r}
}
It's very common for code (especially code fully under your control) to assume you initialize the data structure correctly. A struct literal is usually used in this case
g := &Graph{
connections: make(map[Vertex][]Vertex),
}
Composite literals work just fine inside a constructor. Contriving an example using the initial question (and naively storing copies of Vertices in the map):
func NewGraph(v1 Vertex, v2 Vertex) *Graph {
return &Graph{ map[Vertex][]Vertex{ v1: []Vertex{v2}, v2: []Vertex{v1} }}
}
func main() {
v1 := Vertex{"v1"}
v2 := Vertex{"v2"}
g := NewGraph(v1, v2)
fmt.Println(g)
}
https://play.golang.org/p/Lf4Gomp4tJ

Changing a slice by passing its pointer

I have a slice that I want to change (for example i want to remove the first element) using a function. I thought to use a pointer, but I still can't index it. What am I doing wrong?
Playground link:
func change(list *[]int) {
fmt.Println(*list)
*list = *list[1:] //This line screws everything up
}
var list = []int{1, 2, 3}
func main() {
change(&list)
}
You need to use (*list).
func change(list *[]int) {
*list = (*list)[1:]
}
or a different approach that's usually more go idomatic:
func change(list []int) []int {
return list[1:]
}
playground

Find the real caller in method call

I have a struct like this:
type Parent struct {
example string
}
func (p *Parent) GetMyAttr() {
typ := reflect.TypeOf(p).Elem()
for i := 0; i < typ.NumField(); i++ {
p := typ.Field(i)
if !p.Anonymous {
fmt.Println(p.Name, ":", p.Type)
}
}
}
And if I have another struct like this:
type Child struct {
Parent
another string
}
call GetTypeOfMe() in child like this
ch := Child{Parent{"example"},"another"}
ch.GetMyAttr()
is always return example : string .
Is this possible to get Child struct in Parent struct with reflection?
Full code is here http://play.golang.org/p/ej4Xh_V2J1
It doesn't work like this, reflect.TypeOf(p).Elem() will always return Parent you have 2 options, either implement GetMyAttr for each child or use a generic function like :
func GetAttr(i interface{}) {
typ := reflect.Indirect(reflect.ValueOf(i)).Type()
fmt.Println(typ)
for i := 0; i < typ.NumField(); i++ {
p := typ.Field(i)
fmt.Println(p.Name, ":", p.Type)
}
}
No, since you operate on a *Parent, not a *Child.
This would "work" (play.golang)
func (p *Child) GetMyAttr() {...
would output:
Parent : main.Parent
another : string
A Parent doesn't know about the struct which might embed it, so the reflection operates only on Parent struct.
You see a similar issue with "Go Reflection with Embedding", which uses interface{} to get to all the struct passed in parameter.

Resources