Incrementor not functioning - go

I have some code which is supposed to increment a count.
Here is the struct containing the count variable:
type PipelineData struct {
nodeData map[string]map[string]int
lastBurstResults map[string]map[string]string
burstReady map[string]bool
lastExecutionTime map[string]time.Time
currentNodeSize uint64
}
As you can see there is a member entitled currentNodeSize. This variable is intended to increment ever time the function addNodeData is called. You can see that the function addNodeData calls the function addCount which then uses an atomic incrementer.
func (p PipelineData) addNodeData(key string) {
nodeSlot := clusterScenario.GetNodeSlotByHashSlot(key)
i:=p.nodeData[nodeSlot][key]
i++
p.nodeData[nodeSlot][key]=i
p.addCount()
fmt.Println("Adding node count ",p.currentNodeSize)
}
func (p PipelineData) addCount(){
atomic.AddUint64(&p.currentNodeSize, 1)
}
Unfortunately, when I run this:
p.addNodeData("{pipelinetest}.key");
p.addNodeData("{pipelinetest}.key");
p.addNodeData("{pipelinetest}.key");
p.addNodeData("{pipelinetest}.key");
p.addNodeData("{pipelinetest}.key");
p.addNodeData("{pipelinetest}.key");
Dump(p.currentNodeSize)
The output is 0.
Here is the initialization of the PipelineData struct:
p = &PipelineData{
nodeData:make(map[string]map[string]int,0),
lastBurstResults:make(map[string]map[string]string,0),
burstReady:make(map[string]bool,0),
lastExecutionTime:make(map[string]time.Time,0),
currentNodeSize:0,
}
for i,_ := range clusterScenario.masterNodes{
p.nodeData[i]=make(map[string]int,0)
}
I understand the community has asked me to do my research. I'm not sure what to do at the point. Any help would be appreciated.
I also tried a general incrementor using a variable and that produced the same result which is why I tried an atomic incrementor

addCount takes a value receiver, not a pointer, so it's operating on a copy of the struct, incrementing the field of the copy and then discarding the copy. Change it instead to take a pointer:
func (p *PipelineData) addCount(){
This should resolve your issue.

Related

GO - Pointer or Variable in WaitGroups reference

According the following function declarations from sync package:
Add -------> func (wg *WaitGroup) Add(delta int)
Done ------> func (wg *WaitGroup) Done()
Wait ------> func (wg *WaitGroup) Wait()
I understand that all 3 of them are called by a pointer to a WaitGroup, right?
If this is correct, I don't understand in the next pice of code, why Done function is called using a pointer variable, but Add and Wait functions are called using a variable (not a pointer):
package main
import (
"fmt"
"sync"
"time"
)
func worker(id int, wg *sync.WaitGroup) {
defer wg.Done()
fmt.Printf("Worker %d starting\n", id)
time.Sleep(time.Second)
fmt.Printf("Worker %d done\n", id)
}
func main() {
var wg sync.WaitGroup
for i := 1; i <= 5; i++ {
wg.Add(1)
go worker(i, &wg)
}
wg.Wait()
}
Thanks a lot for your help.
Done, Add and Wait are called on pointer. All functions refer to a pointer receiver *WaitGroup. The fact that you declare variable as value of WaitGroup doesn't mean much as all those methods will all access and modify the variable. The only problem happens when you want to pass your variable to worker - if you try to pass it as value you will make a copy and then Done will be referring to different pointer than Add and Wait - that's why you pass it's address with &.
I think here is best explanation I so far seen on the topic: https://github.com/golang/go/wiki/MethodSets#variables
In general, when you have a variable of a type, you can pretty much call whatever you want on it. When you combine the two rules above together, the following is valid:
type List []int
func (l List) Len() int { return len(l) }
func (l *List) Append(val int) { *l = append(*l, val) }
func main() {
// A bare value
var lst List
lst.Append(1)
fmt.Printf("%v (len: %d)\n", lst, lst.Len())
// A pointer value
plst := new(List)
plst.Append(2)
fmt.Printf("%v (len: %d)\n", plst, plst.Len())
}
Note that both pointer and value methods can both be called on both pointer and non-pointer values. To understand why, let's examine the method sets of both types, directly from the spec:
List
- Len() int
*List
- Len() int
- Append(int)
Notice that the method set for List does not actually contain Append(int) even though you can see from the above program that you can call the method without a problem. This is a result of the second spec section above. It implicitly translates the first line below into the second:
lst.Append(1)
(&lst).Append(1)
Now that the value before the dot is a *List, its method set includes Append, and the call is legal.
To make it easier to remember these rules, it may be helpful to simply consider the pointer- and value-receiver methods separately from the method set. It is legal to call a pointer-valued method on anything that is already a pointer or whose address can be taken (as is the case in the above example). It is legal to call a value method on anything which is a value or whose value can be dereferenced (as is the case with any pointer; this case is specified explicitly in the spec).

Why is value changing after function execution?

I'm currently teaching myself Go, and I'm having trouble understanding a certain behavior:
package main
import (
"fmt"
)
type List struct {
n int
}
func (l List) Increment() {
l.n += 1
l.LogState() // size: 1
}
func (l List) LogState() {
fmt.Printf("size: %v\n", l.n)
}
func main() {
list := List{}
list.Increment()
fmt.Println("----")
list.LogState() // size: 0
}
https://play.golang.org/p/-O24DiNPkxx
LogState is executed twice. The initial time, during the Increment call, it prints size: 1 but after Increment has returned it prints size: 0. Why are those values different?
The reason your nodes are not added to the original linkedList because you are not using pointer to the struct. So even if the Increment function in your example code changes the value. The copy of the struct is changed not the actual struct.
You can declare methods with pointer receivers. This means the
receiver type has the literal syntax *T for some type T. (Also, T
cannot itself be a pointer such as *int.)
If you want to change the linkedlistNode struct counter to show the nodes added to the list you should be using a pointer type receiver on both methdos working to modify the linked list as:
func (l *LinkedList) AddInitialValue(v interface{})
func (l *LinkedList) LogState()
And Inside the main pass an address to the linkedList to use those pointer type receivers as:
func main() {
list := &LinkedList{}
list.AddInitialValue(9)
fmt.Println("----")
list.LogState() // size: 0
}
Working Code Go playground
Note:-
There are two reasons to use a pointer receiver.
To modify the value that its receiver points to.
To avoid copying the value on each method call. This can be more efficient if the receiver is a large struct
For more information go through Method Sets
With Increment and LogState defined the way you've defined them, you are working only with the copy of the value of List. This means that if you make some changes inside Increment function, they are visible only inside Increment's function scope and only for the remainder of that particular scope's existence. To confirm you are always working with a copy of of the initial List value, you can log &list before executing Increment function and &l inside the same function.
If you want to make changes permanent, you should work with a pointer to a memory address. That means your your function should be defined like this:
func (l *List) Increment()
func (l *List) LogState()
This way, you are passing a memory reference (pointer to an address in memory) and every time you change a value of l, you are changing it on the passed memory reference and it reflects everywhere.

Passing pointer to string when the function takes an interface?

I am passing a pointer to a string, to a method which takes an interface (I have multiple versions of the method, with different receivers, so I am trying to work with empty interfaces, so that I don't end up with a ton of boilerplate madness. Essentially, I want to populate the string with the first value in the slice. I am able to see the value get populated inside the function, but then for some reason, in my application which calls it, tha value doesn't change. I suspect this is some kind of pointer arithmetic problem, but could really use some help!
I have the following interface :
type HeadInterface interface{
Head(interface{})
}
And then I have the following functions :
func Head(slice HeadInterface, result interface{}){
slice.Head(result)
}
func (slice StringSlice) Head(result interface{}){
result = reflect.ValueOf(slice[0])
fmt.Println(result)
}
and... here is my call to the function from an application which calls the mehtod...
func main(){
test := x.StringSlice{"Phil", "Jessica", "Andrea"}
// empty result string for population within the function
var result string = ""
// Calling the function (it is a call to 'x.Head' because I lazily just called th import 'x')
x.Head(test, &result)
// I would have thought I would have gotten "Phil" here, but instead, it is still empty, despite the Println in the function, calling it "phil.
fmt.Println(result)
}
*NOTE : I am aware that getting the first element doesn't need to be this complicated, and could be slice[0] as a straight assertion, but this is more of an exercise in reusable code, and also in trying to get a grasp of pointers, so please don't point out that solution - I would get much more use out of a solution to my actual problem here * :)
As you said in your NOTE, I'm pretty sure this doesn't have to be this complicated, but to make it work in your context:
package main
import (
"fmt"
"reflect"
)
type HeadInterface interface {
Head(interface{})
}
func Head(slice HeadInterface, result interface{}) {
slice.Head(result)
}
type StringSlice []string
func (slice StringSlice) Head(result interface{}) {
switch result := result.(type) {
case *string:
*result = reflect.ValueOf(slice[0]).String()
fmt.Println("inside Head:", *result)
default:
panic("can't handle this type!")
}
}
func main() {
test := StringSlice{"Phil", "Jessica", "Andrea"}
// empty result string for population within the function
var result string = ""
// Calling the function (it is a call to 'x.Head' because I lazily just called th import 'x')
Head(test, &result)
// I would have thought I would have gotten "Phil" here, but instead, it is still empty, despite the Println in the function, calling it "phil.
fmt.Println("outside:", result)
}
The hard part about working with interface{} is that it's hard to be specific about a type's behavior given that interface{} is the most un-specific type. To modify a variable that you pass as a pointer to a function, you have to use the asterisk (dereference) (for example *result) on the variable in order to change the value it points to, not the pointer itself. But to use the asterisk, you have to know it's actually a pointer (something interface{} doesn't tell you) so that's why I used the type switch to be sure it's a pointer to a string.

Go resetting closure variable

I came upon an example of closures in Go here:
https://gobyexample.com/closures
It gives a pretty straight-forward example of closure scoping in Go. I changed how i is initialized from "i := 0" to "i := *new(int)".
func intSeq() func() int {
i := *new(int)
return func() int {
i += 1
return i
}
}
func main() {
// We call `intSeq`, assigning the result (a function)
// to `nextInt`. This function value captures its
// own `i` value, which will be updated each time
// we call `nextInt`.
nextInt := intSeq()
// See the effect of the closure by calling `nextInt`
// a few times.
fmt.Println(nextInt())
fmt.Println(nextInt())
fmt.Println(nextInt())
// To confirm that the state is unique to that
// particular function, create and test a new one.
newInts := intSeq()
fmt.Println(newInts())
}
The output of this is still 1, 2, 3, 1. Does the variable 'i' in intSeq() not get reallocated everytime nextInt() in main() is called?
Take a look at how you implemented intSeq.
func intSeq() func() int {
i := *new(int)
return func() int {
i += 1
return i
}
}
The initialization of i is outside of the function it returns.
So the only time a new pointer is allocated is when you actually call intSeq.
Since you are doing that just two times, that's how many different pointers you got.
That explains why the value is not reset when you just call nextInt (note that executing nextInt means just executing the function returned, which looks like:
func() int {
i += 1
return i
}
That would not reset the value of i but rather keep incrementing it (until you create a new one by calling intSeq again).
I hope that clarifies.
No it doesn't. That's the point of the closure. You are initializing an integer variable and storing it on the heap for use by the function the intSeq() function returns. There is no variable initialization happening in the nextInt() function
You will get a new function that uses a new sequence counter starting at 0 for each call to intSeq()
Edit: to add to this this is a bad way to get the current behavior. A better way would be to create a new sequence type that contains the method nextInt() int. E.g.:
type Sequence struct {
counter int
}
func (s *Sequence) nextInt() int {
s.counter++
return s.counter
}
func main() {
intSeq := new(Sequence)
fmt.Println(intSeq.nextInt())
fmt.Println(intSeq.nextInt())
fmt.Println(intSeq.nextInt())
}
There is no point in doing i := *new(int). That line says:
Allocate a new int
Create a pointer to it
Dereference the pointer
Assign the value to i
This is no different from i := 0 or var int i, but there's the extra step in the middle of creating, dereferencing, and discarding the pointer that never gets used.
If you want a pointer to an int, use i := new(int). *new anywhere is a pointless invocation and a code smell.

What's happening with these pointers?

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.

Resources