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?
Related
I'm getting the linting error
ineffective assignment to field Player.Level (SA4005)go-staticcheck
when I try to use a struct method LevelUp to update the struct's value Player.Level:
func main() {
player := Player{
Name: "Tom",
Level: 0,
}
player.LevelUp()
fmt.Printf("Player level %d\n", player.Level)
}
type Player struct {
Name string
Level int
}
func (p Player) LevelUp() {
p.Level += 1 // linting error here
}
p.Level also remains 0 after calling p.LevelUp(). What is the proper way to call a method that updates the value of a field of the struct this method is attached to?
Output:
Player level 0
Each parameter including the receiver is copied upon entering the function / method. When you return, the changes made to the copy are lost. That's why you get a warning: you modify a field which you never use: you don't use in in the method after the assignment, and you can't possibly use it anywhere else, because after returning from the method, the effect of the assignment is lost.
If you need to retain the changes, you must use a pointer receiver (p *Player) and modify the pointed object (p.Level++ will do just that).
func (p *Player) LevelUp() {
p.Level++
}
This will output (try it on the Go Playground):
Player level 1
See related:
My object is not updated even if I use the pointer to a type to update it
How to modify the value of a simple type through pointer receiver method in Go?
Why can't I append to a slice that's the property of a struct in golang?
I have written inorder traversal in python which works fine.
def inOrderTraverse(tree, array):
if tree is None:
return None
inOrderTraverse(tree.left,array)
array.append(tree.value)
inOrderTraverse(tree.right,array)
return array
However when I try to apply the same logic with GOlang, it does not work.
type BST struct {
Value int
Left *BST
Right *BST
}
func (tree *BST) InOrderTraverse(array []int) []int {
if tree == nil {
return nil
}
(tree.Left).InOrderTraverse(array)
array = append(array,tree.Value)
(tree.Right).InOrderTraverse(array)
return array
}
In order to fix this I write if statements to prevent the functions from being called if tree.Left is nil. However I am still confused why my original code does not work.
func (tree *BST) InOrderTraverse(array []int) []int {
if tree.Left != nil {
array = tree.Left.InOrderTraverse(array)
}
array = append(array,tree.Value)
if tree.Right != nil {
array = tree.Right.InOrderTraverse(array)
}
return array
}
To summarize, I am trying to write inorder traversal in Go using the same reasoning from python and it is not working. I figured out how to get it to work(the third code block), however I still do not understand why the second code block does not work. It seems like calling the function on the Nil pointer causes an error
A couple of things:
In your 2nd block of code, the reason it does not work is because the result is discarded:
// (tree.Left).InOrderTraverse(array) // the return result is ignored
array = (tree.Left).InOrderTraverse(array) // capture it like so
Python uses pass by-reference; Go passes by value. As such it can get tricky especially when modifying things like slices in Go.
Since you're already returning the results of the traversal, passing in the array is actually redundant.
Pulling this all together to fix both left & right traversal - and using a return variable result:
func (tree *BST) InOrderTraverse() (result []int) {
if tree == nil {
return // implicitly returns empty `result`
}
result = append(result, (tree.Left).InOrderTraverse()...)
result = append(result, tree.Value)
result = append(result, (tree.Right).InOrderTraverse()...)
return // implicitly returns `result`
}
Working example: https://play.golang.org/p/AUvgZTABiU9
EDIT
A Go "pass by reference" implementation - where the results slice is passed between calls - looks very similar to your python implementation:
func (tree *BST) InOrderTraverse(result *[]int) {
if tree == nil {
return
}
(tree.Left).InOrderTraverse(result)
*result = append(*result, tree.Value)
(tree.Right).InOrderTraverse(result)
}
https://play.golang.org/p/Pp9-4-y-lmE
Note: *[]int (i.e. a pointer to []int) is needed here, as the slice capacity will change during the recursion. A slice is really just a header with a backing array - so while a function can change a slice's elements - even when copied by value - it cannot make the slice shrink or grow (as is the case here). Passing a pointer allows the slice to be reassigned to a potentially larger backing array.
In golang, Is it possible to create a function that takes a struct with the following constraints:
the struct must not be copied (its relatively big)
the caller must not be able to pass nil
EDIT:
I tried using pointers but that can be set to null. I can't find any good articles on how to use references and it doesn't seem like I can pass by reference.
You can create tiny struct wrapper which holds private pointer to big struct and defines Get method to allow acquisition of this big struct. Inside Get you check if pointer is nil then it panics.
Something like:
type StructHolder struct {
target *BigStruct
}
func (s StructHolder) Get() *BigStruct {
if s.target == nil {
panic("target is nil")
}
return s.target
}
Why would you do this? I'd think its better to pass a pointer and check its value.
I wrote some odd code, but I'm not sure why it works and what I can learn from it. I have a slice type build from another struct. I made a function on the slice type to modify itself. To do this, I seem to have to throw around *'s a little much.
I'm trying to learn about pointers in Go and would like a little help. Here's an example (http://play.golang.org/p/roU3MEeT3q):
var ClientNames = []string {"Client A", "Client B", "ClientC"}
type InvoiceSummaries []InvoiceSummary
type InvoiceSummary struct {
Client string
Amt int
}
func (summaries *InvoiceSummaries) BuildFromAbove() {
for _, name := range ClientNames {
*summaries = append(*summaries, InvoiceSummary{name, 100})
}
}
My question is: What is the purpose for each of these * and why am I not using any &?
What is the purpose for each of these * ?
By making the method receiver as pointer, you could easily change the property of the object. I think that's one of the benefit. This example below will prove it.
package main
import "fmt"
type someStruct struct {
someVar int
}
func (s someStruct) changeVal1(newVal int) {
s.someVar = newVal
}
func (s *someStruct) changeVal2(newVal int) {
s.someVar = newVal
}
func main() {
s := someStruct{0}
fmt.Println(s) // {0}
s.changeVal1(3)
fmt.Println(s) // {0}
s.changeVal2(4)
fmt.Println(s) // {4}
(&s).changeVal2(5)
fmt.Println(s) // {5}
}
and why am I not using any &?
Pointer method receiver is quite special, it can also be called from non-pointer struct object. Both of s.changeVal2(4) and (&s).changeVal2(5) are valid & will affect the value of someVar.
Example http://play.golang.org/p/sxCnCD2D6d
You have to use a pointer for the receiver - (summaries *InvoiceSummaries) - because otherwise the argument is passed by value, having a pointer means you pass a reference to the value instead. If not for that, then you couldn't modify the collection at all.
Inside of the methods body you have use * because it is the dereferncing operator and returns the value at the address. Ampersand (&) is the opposite, it gives the address of a value.
Nothing wrong with your code but normally addresses to slices aren't used. A slice is a small struct that gophers are normally happy to pass by value. If a method or function is creating a new slice, the gopher is happy to return the new slice, by value again, as the return value.
Of course passing a slice by value doesn't guarantee anything about the backing store remaining unchanged when the method/function returns. So it can't be used as a way of guaranteeing the data elements of the slice haven't mutated.
The slices are references to the underlying array. This makes sense and seems to work on builtin/primitive types but why is not working on structs? I assume that even if I update a struct field the reference/address is still the same.
package main
import "fmt"
type My struct {
Name string
}
func main() {
x := []int{1}
update2(x)
fmt.Println(x[0])
update(x)
fmt.Println(x[0])
my := My{Name: ""}
update3([]My{my})
// Why my[0].Name is not "many" ?
fmt.Println(my)
}
func update(x []int) {
x[0] = 999
return
}
func update2(x []int) {
x[0] = 1000
return
}
func update3(x []My) {
x[0].Name = "many"
return
}
To clarify: I'm aware that I could use pointers for both cases. I'm only intrigued why the struct is not updated (unlike the int).
What you do when calling update3 is you pass a new array, containing copies of the value, and you immediately discard the array. This is different from what you do with the primitive, as you keep the array.
There are two approaches here.
1) use an array of pointers instead of an array of values:
You could define update3 like this:
func update3(x []*My) {
x[0].Name = "many"
return
}
and call it using
update3([]*My{&my})
2) write in the array (in the same way you deal with the primitive)
arr := make([]My,1)
arr[0] = My{Name: ""}
update3(arr)
From the GO FAQ:
As in all languages in the C family, everything in Go is passed by
value. That is, a function always gets a copy of the thing being
passed, as if there were an assignment statement assigning the value
to the parameter. For instance, passing an int value to a function
makes a copy of the int, and passing a pointer value makes a copy of
the pointer, but not the data it points to. (See the next section for
a discussion of how this affects method receivers.)
Map and slice values behave like pointers: they are descriptors that
contain pointers to the underlying map or slice data. Copying a map or
slice value doesn't copy the data it points to.
Thus when you pass my you are passing a copy of your struct and the calling code won't see any changes made to that copy.
To have the function change the data in teh struct you have to pass a pointer to the struct.
Your third test is not the same as the first two. Look at this (Playground). In this case, you do not need to use pointers as you are not modifying the slice itself. You are modifying an element of the underlying array. If you wanted to modify the slice, by for instance, appending a new element, you would need to use a pointer to pass the slice by reference. Notice that I changed the prints to display the type as well as the value.