Trying to implement LinkedList with simple addToLast function (which adds the new node to the end of the linkedlist) instead of using the inbuilt list)
Below is the code (removed print statements which I used for debugging):
package main
import "fmt"
var first *Link
var last Link
func main() {
AddToLast(10)
AddToLast(20)
}
func AddToLast(d int) {
if first == nil {
last = Link{d, new(Link)}
first = &last
} else {
last.next = &Link{d, new(Link)}
last = *last.next
}
}
type Link struct {
data int
next *Link
}
My understanding of the above code:
Inside AddToLast functions -
After checking if 'first' is nil i.e. it doesn't have any element, 'last' is created
with 10 as the data and new empty Link as the next. Now 'first' is assigned the same value
as 'last' but using memory address(as reference - I'm not sure if my understanding is incorrect here)
Now when we try to insert 20 (the next new element) the else part in the 'AddToLast' is executed.
'last.next' is assigned a link with value as 20 and it's next as nil. Now 'last' is moved to 'last.next',
to make sure 'last' always points to the last node.
However since I moved 'last' to 'last.next', 'last'('s) memory address changes which is obvious and this also
causes first to point to the new last i.e. with value as 20.
In order to avoid this, I tried declaring 'first' as Link instead of *Link.
However, doing this doesn't make first.next point to new node i.e. 20. I'm confused as to where I'm not thinking correct.
Don't mutate the element value in last, since that element is already created. Make a new last, and set the previous next pointer to point to it. Here is a modified version: http://play.golang.org/p/-X5RayC0gU
var first *Link
var last *Link
func AddToLast(d int) {
next := &Link{d, nil}
if first == nil {
first = next
} else {
last.next = next
}
last = next
}
type Link struct {
data int
next *Link
}
Related
I'm trying to implement LinkedList operation in Golang from scratch. But I found a problem when dealing with removing first element. My approach is using OOP style, but it seems the first element is not removed. This is the code I write,
type LinkedList struct {
Value int
next *LinkedList
}
func (ll *LinkedList) Remove(index int) error {
pointer := ll
var pointerPrev *LinkedList = nil
current := 0
for current < index {
pointerPrev = pointer
pointer = pointer.next
current++
}
if pointer == ll {
ll = ll.next // this line is problematic
pointer = nil
} else {
if pointer.next == nil {
pointerPrev.next = nil
} else {
pointerPrev.next = pointer.next
pointer = nil
}
}
return nil
}
Any suggestion how I implement this way of removing without returning new LinkedList pointer?
Everything is passed as a copy, so you can only change something if a pointer to it is passed, and you modify the pointed value.
So you can't do what you want without having to return the new list head (which you have to assign at the caller).
An alternative could be to pass the address of the head pointer (type of **LinkedList), which is ugly (having to always pass the head pointer's address). You could also add a separate method for removing the first element, something like RemoveFirst(), so you only have to pass to this method only. This RemoveFirst() could return the new head too, which the caller has to assign. This RemoveFirst() could also be a "regular" function instead of a method.
Another alternative is to create a wrapper for the list, which holds a pointer to the head. And you implement methods on the wrapper, not on the node type. And a method of the wrapper could change the field holding the head pointer.
See related: Can the pointer in a struct pointer method be reassigned to another instance?
I have a JSON file named test.json which contains:
[
{
"name" : "john",
"interests" : ["hockey", "jockey"]
},
{
"name" : "lima",
"interests" : ["eating", "poker"]
}
]
Now I have written a golang script which reads the JSON file to an slice of structs, and then upon a condition check, modifies a struct fields by iterating over the slice.
Here is what I've tried so far:
package main
import (
"log"
"strings"
"io/ioutil"
"encoding/json"
)
type subDB struct {
Name string `json:"name"`
Interests []string `json:"interests"`
}
var dbUpdate []subDB
func getJSON() {
// open the file
filename := "test.json"
val, err := ioutil.ReadFile(filename)
if err != nil {
log.Fatal(err)
}
err = json.Unmarshal(val, &dbUpdate)
}
func (v *subDB) Change(newresponse []string) {
v.Interests = newresponse
}
func updater(name string, newinterest string) {
// iterating over the slice of structs
for _, item := range dbUpdate {
// checking if name supplied matches to the current struct
if strings.Contains(item.Name, name) {
flag := false // declare a flag variable
// item.Interests is a slice, so we iterate over it
for _, intr := range item.Interests {
// check if newinterest is within any one of slice value
if strings.Contains(intr, newinterest) {
flag = true
break // if we find one, we terminate the loop
}
}
// if flag is false, then we change the Interests field
// of the current struct
if !flag {
// Interests holds a slice of strings
item.Change([]string{newinterest}) // passing a slice of string
}
}
}
}
func main() {
getJSON()
updater("lima", "jogging")
log.Printf("%+v\n", dbUpdate)
}
The output I'm getting is:
[{Name:john Interests:[hockey jockey]} {Name:lima Interests:[eating poker]}]
However I should be getting an output like:
[{Name:john Interests:[hockey jockey]} {Name:lima Interests:[jogging]}]
My understanding was that since Change() has a pointer passed, it should directly modify the field. Can anyone point me out what I'm doing wrong?
The problem
Let's cite what the language specification says on the for ... range loops:
A "for" statement with a "range" clause iterates through all entries
of an array, slice, string or map, or values received on a channel.
For each entry it assigns iteration values to corresponding iteration
variables if present and then executes the block.
So, in
for _, item := range dbUpdate { ... }
the whole statement forms a scope in which a variable named item is declared and it gets assigned a value of each element of dbUpdate, in turn, form the first to the last — as the statement performs its iterations.
All assignments in Go, always and everywhere do copy the value of the expression being assigned, into a variable receiving that value.
So, when you have
type subDB struct {
Name string `json:"name"`
Interests []string `json:"interests"`
}
var dbUpdate []subDB
you have a slice whose backing array contains a set of elements, each of which has type subDB.
Consequently, when for ... range iterates over your slice, on each iteration a shallow copy of the fields of a subDB value contained in the current slice element is done: the values of those fields are copied into the variable item.
We could re-write what happes as this:
for i := 0; i < len(dbUpdate); i++ {
var item subDB
item = dbUpdate[i]
...
}
As you can see, if you mutate item in the loop's body, the changes you do to it do not in any way affect the collection's element currently being iterated over.
The solutions
Broadly speaking, the solution is to become fully acquainted with the fact that Go is very simple in most of the stuff it implements, and so range is no magic to: the iteration variable is just a variable, and assignment to it is just an assignment.
As to solving the particular problem, there are multiple ways.
Refer to a collection element by its index
Do
for i := range dbUpdate {
dbUpdate[i].FieldName = value
}
A corollary to this is that sometimes, when the element is complex or you'd like to delegate its mutation to some function, you may take a pointer to it:
for i := range dbUpdate {
p := &dbUpdate[i]
mutateSubDB(p)
}
...
func mutateSubDB(p *subDB) {
p.SomeField = someValue
}
Keep pointers in the slice
If your slice were declated like
var dbUpdates []*subDB
…and you'd keep pointers to (usually heap-allocated) SubDB values,
the
for _, ptr := range dbUpdate { ... }
statement would naturally copy a pointer to a SubDB (anonymous) variable into ptr as the slice contains pointers and so the assignment copies a pointer.
Since all pointers containing the same address are pointing to the same value, mutating the target variable through the pointer kept in the iteration variable would mutate the same thing which is pointed to by the slice's element.
Which approach to select should usually depend on considerations other than thinking about how one would iterate over the elements — simply because once you understand why your code did not work, you do not have this problem anymore.
As usually: if your values are really big, consider keeping pointers to them.
If you values need to be referenced from multiple places at the same time, keep pointers to them. In other cases keep the values directly — this greatly improves CPU data cache locality (simply put, by the time you're about to access the next element its contents will most likely have been already fetched from the memory, which does not occur when the CPU has to chase a pointer to access some arbitrary memory location through it).
I wanted to create a map of slices where values are appended to the corresponding slice. However, when trying to append directly to the slice returned by accessing it (see comment below), it would not be stored, so I had to go with the long form access (line below the comment).
Why is it so? I expected the access to the map to return some sort of pointer, so in my mind mappedAminoAcid == aminoAcidsToCodons[aminoAcid]; clearly, I'm wrong.
Thanks!
aminoAcidsToCodons := map[rune][]string{}
for codon, aminoAcid := range utils.CodonsToAminoAcid {
mappedAminoAcid, ok := aminoAcidsToCodons[aminoAcid]
if ok {
// NOT WORKING: mappedAminoAcid = append(mappedAminoAcid, codon)
aminoAcidsToCodons[aminoAcid] = append(mappedAminoAcid, codon)
} else {
aminoAcidsToCodons[aminoAcid] = []string{codon}
}
}
append returns a new slice if the underlying array has to grow to accomodate the new element. So yes, you have to put the new slice back into the map. This is no different from how strings work, for instance:
var x map[string]string
x["a"] = "foo"
y := x["a"]
y = "bar"
// x["a"] is still "foo"
Since a nil slice is a perfectly fine first argument for append, you can simplify your code to:
aminoAcidsToCodons := map[rune][]string{}
for codon, aminoAcid := range utils.CodonsToAminoAcid {
aminoAcidsToCodons[aminoAcid] = append(aminoAcidsToCodons[aminoAcid], codon)
}
What I understand about pointer method receiver and non-pointer method receiver is first one can be modified in the method and next one isn't.
So, following worked exactly as I expected.
type student struct {
name string
age int
}
func (s *student) update() {
s.name = "unknown"
s.age = 0
}
func main() {
s := student{"hongseok", 13}
fmt.Println(s)
s.update()
fmt.Println(s)
}
It prints hongseok/13 and unknown/0.
But, I want to replace whole s in update method at once with reassigning. So, I've just altered update method as bellow.
func (s *student) update() {
s = &student{"unknown", 0}
}
And it doesn't change s in main method and prints double hongseok/13.
func (s *student) update() {
*s = student{"unknown", 0}
}
Above change fix the problem.
I think there's no semantic difference. What am I missing?
In the first example:
func (s *student) update() {
s = &student{"unknown", 0}
}
You are assigning an entirely new "pointer value" to s, and the new *s points at a new student value. The variable s is scoped only to the method body, so there are no side effects after this returns.
In the second example
func (s *student) update() {
*s = student{"unknown", 0}
}
You are dereferencing s, and changing the value of *s to point to a new student value, or to put it differently, you are putting a new student value at the address where s points.
In this example you're changing the address that is stored in s to a different value;
func (s *student) update() {
s = &student{"unknown", 0}
}
While using a pointer is regarded as 'passing by reference' the reference itself is a value like any other that is pushed onto the call stack. When you return to main, the value of s is whatever it was in that scope. So to give something more concrete, you called main with s = 1 (calling the addresses 1 and 2 for simplicity), in the method you allocate a new student located at address 2 and you set s = 2, when you return that version of s is popped from the stack and the s in main points to 1 which is unchanged.
In this latter example;
func (s *student) update() {
*s = student{"unknown", 0}
}
You're dereferencing s and assigning a new object to that location, overwriting the existing memory. When you return the pointer in main is still pointing to the same location but you have different data at that location in memory. So in this example you're writing a new student instance to address 1 so when you return you see the new value in the calling scope.
I think, your main problem is that you don't understand well neither one of two concepts that appear in your question.
Let start with pointers. When you don't use pointers, assigning of value means create a simple copy of previous value. The new value is not bound any way with previous one. That means if you change the old value or new, it does not influence the second one. This is normal for primitive types (like ints, bool, string) and structures.
a := 1
b := a
a++ // a was changed, but value of b does not change at all
And now the pointers - it is something that points to some space into memory. For simplicity we create two pointers and both will point to same place.
package main
import (
"fmt"
)
func main() {
type student struct {
name string
age int
}
p1 := &student{"hongseok", 13} // this mean create a new student, but we want only address of student, not value
p2 := p1
(*p1).age = 15 // because p1 and p2 point to same memory (*p2).age also changed
fmt.Println("1.", p2.age) // 15
p2.age = 32 // in golang I could write (*p2).ago or p2.ago this is the same
fmt.Println("2.", p1.age) // 32
fmt.Println("3.",p1, "==", p2)
fmt.Printf("4. %p == %p\n", p1, p2)
// But now I force point p2 to new place
p2 = &student{"another student", 12}
fmt.Println("5.", p1, "!=", p2)
fmt.Printf("6. %p == %p\n", p1, p2)
p1.age = 14 // does it influce p2.age? no! Why? Because it is in different address
fmt.Println("7.", p1, "!=", p2)
// but could is somehow force that point to same address ? Of course
p2 = p1 // p2 will point to same place as p1 and old value of p2 will be freed by garbage collector
}
And don't be confused - pointer can also points named value.
a := 42 // means allocate memory for integer, and we give that memory name "a"
p := &a
*p++ // it change value of a
a = 5 // and of course this change value of *p
And now back to methods, that receiver is/is not a pointer. If receiver of method is pointer, that means you can change it value - the same way as I did few lines ago.
If method receiver is not a pointer, that means - before calling a method, it will be created a copy of struct and method will be called on that copy. You of course can change value of copy, but it does not influence original value.
I created an Element struct that has a parent and children, created a helper func called SubElement, and a String method that iterates through all children for print:
package main
import "fmt"
type Element struct {
parent *Element
children []Element
tag string
}
func SubElement(parent *Element, tag string) Element {
el := Element{}
el.parent = parent
el.tag = tag
parent.children = append(parent.children, el)
return el
}
func (el Element) String() string {
s := "<" + el.tag + ">"
for _, child := range el.children {
s += child.String()
}
s += "</" + el.tag + ">"
return s
}
func main() {
root := Element{}
root.tag = "root"
a := SubElement(&root, "a")
b := SubElement(&a, "b")
SubElement(&b, "c")
fmt.Println(root) // prints: <root><a></a></root>
fmt.Println(a) // prints: <a><b></b></a>
// and so on
}
The problem I'm experiencing is, only the first tier of children are available from the root node I choose to print. I'm sure it's related to the use of append on parent.children, but lack the understanding of how to resolve this correctly.
To work around the issue, I changed children to map[int]Element. Then in my SubElement func, I "append" with parent.children[len(parent.children)] = el. Then to iterate in the correct order, the String method for-loop is for i:= 0; i < len(el.children); i++, accessing el.children[i].
Still, I'd like to know how to do this correctly with an array. Thanks
An answer to explain why the []Element version didn't work.
Structs are copied as values. In SubElement, you create one Element struct, then when you append it, that actually appends a whole new copy of the struct. When you return el and assign it to a, that makes yet another copy. The address of a is not the address of the Element that was appended.
So, you could get tricky and take the address of the element that's actually in the slice, and that might even look like it's working in a test case, but there's a problem with retaining one these pointers such as you do when you store it back in Element.parent. The problem is that a subsequent append can reallocate the slice, and now your retained pointer points into some orphaned memory rather than the currently valid slice.
If the []*Element version solved some other issues, it's likely that they were issues of storing pointers that were subseqently orphaned.
It is possible to implement a tree with slices of structs, but it takes a clear understanding that retaining pointers into slices is usually a mistake. Since storing the parent pointer is not safe, it's best to just remove it from the struct.
package main
import "fmt"
func main() {
tree := Element{tag: "head"}
tree.SubElement("tier-1")
tree.children[0].SubElement("tier-2")
tree.children[0].SubElement("tier-2")
tree.SubElement("tier-1")
tree.children[1].SubElement("tier-2")
fmt.Println(tree)
}
type Element struct {
children []Element
tag string
}
func (parent *Element) SubElement(tag string) {
parent.children = append(parent.children, Element{tag: tag})
}
func (el Element) String() string {
s := "<" + el.tag + ">"
for _, child := range el.children {
s += child.String()
}
s += "</" + el.tag + ">"
return s
}
This code, at least, works; but if you had other code that was working with pointers, or that used the parent pointer, it would have to be rethought.
The first clue is that SubElement doesn't compile as you have it (edit: had it) there (originally.) You could experiment with making it work, but I recommend you change the Element.children to be []*Element rather than []Element. Here's a working example:
package main
import "fmt"
func main() {
tree := &Element{tag: "head"}
t1 := SubElement(tree, "tier-1")
SubElement(t1, "tier-2")
SubElement(t1, "tier-2")
t1 = SubElement(tree, "tier-1")
SubElement(t1, "tier-2")
fmt.Println(tree)
}
type Element struct {
parent *Element
children []*Element
tag string
}
func SubElement(parent *Element, tag string) *Element {
el := &Element{parent: parent, tag: tag}
parent.children = append(parent.children, el)
return el
}
func (el *Element) String() string {
s := "<" + el.tag + ">"
for _, child := range el.children {
s += child.String()
}
s += "</" + el.tag + ">"
return s
}
Output:
<head><tier-1><tier-2></tier-2><tier-2></tier-2></tier-1><tier-1><tier-2></tier-2></tier-1></head>