-1

Please consider the code https://play.golang.org/p/aO07_PoQLuh

I've a list of structs, which I read from to get an idea of the members I've generated enroute.

For each struct, I've a method to raise a counter, however I am missing the sauce here. As you can see from the o/p, I've incremented SBytesSent, but when I read the list of struct and inspect it, it is at 0.

What's the best way to handle this? Thanks!

package main

import (
    "fmt"
    "sync"
)

type destination struct {
    Name          string
    SBytesSent    int64
    ABytesSent    int64
    LastSeenAlive int64
    Mutex         *sync.Mutex
}

type destinations []destination

var (
    destination_list destinations
    myHosts          = []string{"host1", "host2", "host3"}
)

func main() {
    fmt.Println("Hello, playground")
    for i, _ := range myHosts {
        newDest := myHosts[i]
        newd := destination{Name: newDest}
        newd.Mutex = &sync.Mutex{}
        destination_list = append(destination_list, newd)
    }
    i := 0
    for {
        increment()
        status()
        i += 1
        if i == 3 {
            break
        }
    }

}

func (self *destination) incrementSBytes(a int) {
    self.Mutex.Lock()
    defer self.Mutex.Unlock()
    self.SBytesSent += int64(a)
    fmt.Printf("new val %d\n", self.SBytesSent)
}

func (self *destination) Status() {
    fmt.Printf("my val %d\n", self.SBytesSent)
}

func increment() {
    for i, _ := range destination_list {
        dest := destination_list[i]
        dest.incrementSBytes(33)
    }
}

func status() {
    for i, _ := range destination_list {
        dest := destination_list[i]
        dest.Status()
    }
}

Edit 1

Please see https://play.golang.org/p/5uqqc3OKYDs - I've incremented host3 to 6 - yet towards the end they all show 99. How can I make host3 retain the previous increment and show 99 + 6 = 105?

struggling_learner
  • 1,214
  • 15
  • 29
  • 2
    The problem with the code in the playground is of the same nature as your original problem: `blueHost` is a copy of `destination_list[2]`. You could have avoided both problems by using pointers. See [here](https://play.golang.org/p/uImzdBb7D9Z), now `host3` is 105 and also your previous version of `increment` works as you would expect. – mkopriva Dec 10 '19 at 08:06
  • @mkopriva - please add as answer so I can mark it as accepted answer. thanks! – struggling_learner Dec 10 '19 at 17:45

2 Answers2

4

It doesn't work, because you're copying, and modifying the copy:

dest := destination_list[i]
dest.incrementSBytes(33)

Above, you first copy the array element to dest, and then modify dest. Array element never changes. Instead try this:

destination_list[i].incrementsSBytes(33)
Burak Serdar
  • 46,455
  • 3
  • 40
  • 59
3

All the magic lies in the range, it creates a copy of that element and hence the modification wasn't visible.

Read more about it: Change values while iterating

package main

import (
    "fmt"
    "sync"
)

type destination struct {
    Name          string
    SBytesSent    int64
    ABytesSent    int64
    LastSeenAlive int64
    Mutex         *sync.Mutex
}

type destinations []destination

var (
    destination_list destinations
    myHosts          = []string{"host1", "host2", "host3"}
)

func main() {
    fmt.Println("Hello, playground")
    for i := range myHosts {
        newDest := myHosts[i]
        newd := destination{Name: newDest}
        newd.Mutex = &sync.Mutex{}
        destination_list = append(destination_list, newd)
    }
    i := 0
    for {
        increment()
        status()
        i++
        if i == 3 {
            break
        }
    }

}

func (self *destination) incrementSBytes(a int) {
    self.Mutex.Lock()
    defer self.Mutex.Unlock()
    self.SBytesSent += int64(a)
    fmt.Printf("new val %d\n", self.SBytesSent)
}

func (self *destination) Status() {
    fmt.Printf("my val %d\n", self.SBytesSent)
}

func increment() {
    for i:=0; i<len(destination_list); i++ {
        destination_list[i].incrementSBytes(33)
    }
}

func status() {
    for i:=0; i<len(destination_list); i++ {
        destination_list[i].Status()
    }
}

Output:

Hello, playground
new val 33
new val 33
new val 33
my val 33
my val 33
my val 33
new val 66
new val 66
new val 66
my val 66
my val 66
my val 66
new val 99
new val 99
new val 99
my val 99
my val 99
my val 99
shmsr
  • 3,802
  • 2
  • 18
  • 29