tags:

views:

76

answers:

2

To define a map from int to struct vertex, should I define map[int]vertex or map[int]*vertex? Which one is preferred?

I extended Chickencha's code:

package main

type vertex struct {
    x, y int 
}

func main() {
    a := make(map[int]vertex)
    b := make(map[int]*vertex)

    v := &vertex{0, 0}
    a[0] = *v
    b[0] = v 

    v.x, v.y = 4, 4
    println(a[0].x, a[0].y, b[0].x, b[0].y)

    //a[0].x = 3 // cannot assign to (a[0]).x
    //a[0].y = 3 // cannot assign to (a[0]).y
    b[0].x = 3 
    b[0].y = 3 
    println(a[0].x, a[0].y, b[0].x, b[0].y)

    u1 := a[0]
    u1.x = 2 
    u1.y = 2 
    u2 := b[0]
    u2.x = 2 
    u2.y = 2 
    println(a[0].x, a[0].y, b[0].x, b[0].y)
}

The output:

0 0 4 4
0 0 3 3
0 0 2 2

From the output, my understanding is, if I want to change the struct member in place, I must use pointer to the struct. But I'm still not sure the underlying reasons. Especially, why I cannot assign to a[0].x?

A: 

The answer to this question is likely to be dependent on how Go maps are implemented. For the current implementation, I would take a look the Go map runtime header, hashmap.h, and code, hashmap.c, files. It's also going to depend on how you use the map e.g. what type and volume of activities against the map, key and element data structures, etc.

To update a vector element value in place, read the vector element value from the map, update the element value, write the updated element value to the map. For example

package main

type vertex struct {
    x, y int
}

func main() {
    a := make(map[int]vertex)
    a[0] = vertex{0, 0}

    println(a[0].x, a[0].y)
    v0 := a[0]
    v0.x = 1
    a[0] = v0
    println(a[0].x, a[0].y)
}

Output:

0 0
1 0
peterSO
A: 

The main difference is that map[int]vertex stores vertex values and map[int]*vertex stores vertex references (pointers). The output of the following program should help illustrate:

package main

type vertex struct {
    x, y int
}

func main() {
    a := make(map[int]vertex)
    b := make(map[int]*vertex)

    v := &vertex{0, 0}
    a[0] = *v
    b[0] = v

    v.x, v.y = 4, 4
    println(a[0].x, a[0].y, b[0].x, b[0].y)
}

Output:

0 0 4 4

The vertex stored in b is modified by the v.x, v.y = 4, 4 line, while the vertex stored in a is not.

Evan Shaw
`map[int]vertex` stores a value and `map[int]*vertex` stores a pointer for the map element. In Go, slices, maps, and channels are reference types.
peterSO
Right, I guess my wording could've been unclear. I'll edit it so hopefully it says what I mean.
Evan Shaw