panic: assignment to entry in nil map on single simple map - dictionary

I was under the impression that the assignment to entry in nil map error would only happen if we would want to assign to a double map, that is, when a map on a deeper level is trying to be assigned while the higher one doesn't exist, e.g.:
var mm map[int]map[int]int
mm[1][2] = 3
But it also happens for a simple map (though with struct as a key):
package main
import "fmt"
type COO struct {
x int
y int
}
var neighbours map[COO][]COO
func main() {
for i := 0; i < 30; i++ {
for j := 0; j < 20; j++ {
var buds []COO
if i < 29 {
buds = append(buds, COO{x: i + 1, y: j})
}
if i > 0 {
buds = append(buds, COO{x: i - 1, y: j})
}
if j < 19 {
buds = append(buds, COO{x: i, y: j + 1})
}
if j > 0 {
buds = append(buds, COO{x: i, y: j - 1})
}
neighbours[COO{x: i, y: j}] = buds // <--- yields error
}
}
fmt.Println(neighbours)
}
What could be wrong?

You need to initialize neighbours: var neighbours = make(map[COO][]COO)
See the second section in: https://blog.golang.org/go-maps-in-action
You'll get a panic whenever you try to insert a value into a map that hasn't been initialized.

In Golang, everything is initialized to a zero value, it's the default value for uninitialized variables.
So, as it has been conceived, a map's zero value is nil. When trying to use an non-initialized map, it panics. (Kind of a null pointer exception)
Sometimes it can be useful, because if you know the zero value of something you don't have to initialize it explicitly:
var str string
str += "42"
fmt.Println(str)
// 42 ; A string zero value is ""
var i int
i++
fmt.Println(i)
// 1 ; An int zero value is 0
var b bool
b = !b
fmt.Println(b)
// true ; A bool zero value is false
If you have a Java background, that's the same thing: primitive types have a default value and objects are initialized to null;
Now, for more complex types like chan and map, the zero value is nil, that's why you have to use make to instantiate them. Pointers also have a nil zero value. The case of arrays and slice is a bit more tricky:
var a [2]int
fmt.Println(a)
// [0 0]
var b []int
fmt.Println(b)
// [] ; initialized to an empty slice
The compiler knows the length of the array (it cannot be changed) and its type, so it can already instantiate the right amount of memory. All of the values are initialized to their zero value (unlike C where you can have anything inside your array). For the slice, it is initialized to the empty slice [], so you can use append normally.
Now, for structs, it is the same as for arrays. Go creates a struct with all its fields initialized to zero values. It makes a deep initialization, example here:
type Point struct {
x int
y int
}
type Line struct {
a Point
b Point
}
func main() {
var line Line
// the %#v format prints Golang's deep representation of a value
fmt.Printf("%#v\n", line)
}
// main.Line{a:main.Point{x:0, y:0}, b:main.Point{x:0, y:0}}
Finally, the interface and func types are also initialized to nil.
That's really all there is to it. When working with complex types, you just have to remember to initialize them. The only exception is for arrays because you can't do make([2]int).
In your case, you have map of slice, so you need at least two steps to put something inside: Initialize the nested slice, and initialize the first map:
var buds []COO
neighbours := make(map[COO][]COO)
neighbours[COO{}] = buds
// alternative (shorter)
neighbours := make(map[COO][]COO)
// You have to use equal here because the type of neighbours[0] is known
neighbours[COO{}] = make([]COO, 0)

Related

Does dereferencing a struct return a new copy of struct?

Why when we reference struct using (*structObj) does Go seem to return a new copy of structObj rather than return the same address of original structObj? This might be some misunderstanding of mine, so I seek clarification
package main
import (
"fmt"
)
type me struct {
color string
total int
}
func study() *me {
p := me{}
p.color = "tomato"
fmt.Printf("%p\n", &p.color)
return &p
}
func main() {
p := study()
fmt.Printf("&p.color = %p\n", &p.color)
obj := *p
fmt.Printf("&obj.color = %p\n", &obj.color)
fmt.Printf("obj = %+v\n", obj)
p.color = "purple"
fmt.Printf("p.color = %p\n", &p.color)
fmt.Printf("p = %+v\n", p)
fmt.Printf("obj = %+v\n", obj)
obj2 := *p
fmt.Printf("obj2 = %+v\n", obj2)
}
Output
0x10434120
&p.color = 0x10434120
&obj.color = 0x10434140 //different than &p.color!
obj = {color:tomato total:0}
p.color = 0x10434120
p = &{color:purple total:0}
obj = {color:tomato total:0}
obj2 = {color:purple total:0} // we get purple now when dereference again
Go playground
When you write
obj := *p
You are copying the value of struct pointed to by p (* dereferences p). It is similar to:
var obj me = *p
So obj is a new variable of type me, being initialized to the value of *p. This causes obj to have a different memory address.
Note that obj if of type me, while p is of type *me. But they are separate values. Changing a value of a field of obj will not affect the value of that field in p (unless the me struct has a reference type in it as a field, i.e. slice, map or channels. See here and here.). If you want to bring about that effect, use:
obj := p
// equivalent to: var obj *me = p
Now obj points to the same object as p. They still have different addresses themselves, but hold within them the same address of the actual me object.
No, "assignment" always creates a copy in Go, including assignment to function and method arguments. The statement obj := *p copies the value of *p to obj.
If you change the statement p.color = "purple" to (*p).color = "purple" you will get the same output, because dereferencing p itself does not create a copy.
tl;dr Dereferencing (using the * operator) in Go does not make a copy. It returns the value the pointer points to.

Golang: How to create unknown (dynamic) Map length

I can create a "static" map via
type m map[int]map[int]map[int]bool
but the length of "keys" will be dynamic:
|---unknown len--|
m[1][2][3][4][2][0] = true
or
|---unk len--|
m[1][2][3][4] = true
How I can create this map in Go? Or any way exists?
Added: Hierarchical is IMPORTANT
Thanks in advance!
The map type:
A map is an unordered group of elements of one type, called the element type, indexed by a set of unique keys of another type, called the key type.
A map type must have a specific value type and a specific key type. What you want does not qualify for this: you want a map where the value is sometimes another map (of the same type), and sometimes it's a bool.
Your options:
1. With a wrapper value type
The idea here is to not use just a simple (bool) value type, but a wrapper which holds both of your potential values: both a map and the simple value (bool):
type Value struct {
Children MapType
V bool
}
type MapType map[int]*Value
var m MapType
This is basically what user3591723 suggested, so I won't detail it further.
2. With a tree
This is a variant of #1, but this way we clearly communicate it's a tree.
The cleanest way to implement your hierarchical structure would be to use a tree, where a node could look like this:
type KeyType int
type ValueType string
type Node struct {
Children map[KeyType]*Node
Value ValueType
}
This has the advantage that you may choose the value type (which is bool in your case, but you can change it to whatever type - I used string for presentation).
For easily build / manage your tree, we can add some methods to our Node type:
func (n *Node) Add(key KeyType, v ValueType) {
if n.Children == nil {
n.Children = map[KeyType]*Node{}
}
n.Children[key] = &Node{Value: v}
}
func (n *Node) Get(keys ...KeyType) *Node {
for _, key := range keys {
n = n.Children[key]
}
return n
}
func (n *Node) Set(v ValueType, keys ...KeyType) {
n = n.Get(keys...)
n.Value = v
}
And using it: 1. build a tree, 2. query some values, 3. change a value:
root := &Node{Value: "root"}
root.Add(0, "first")
root.Get(0).Add(9, "second")
root.Get(0, 9).Add(3, "third")
root.Get(0).Add(4, "fourth")
fmt.Println(root)
fmt.Println(root.Get(0, 9, 3))
fmt.Println(root.Get(0, 4))
root.Set("fourthMod", 0, 4)
fmt.Println(root.Get(0, 4))
Output (try it on the Go Playground):
&{map[0:0x104382f0] root}
&{map[] third}
&{map[] fourth}
&{map[] fourthMod}
3. With a recursive type definition
It may be surprising but it is possible to define a map type in Go which has unlimited or dynamic "depth", using a recursive definition:
type X map[int]X
It is what it says: it's a map with int keys, and values of the same type as the map itself.
The big downside of this recursive type is that it can't store any "useful" data in the value type. It can only store the "fact" whether a value is present which is identical to a bool-like information (bool type: true or false), which may be enough in rare cases, but not in most.
Let's see an example building a "tree":
var x X
x = map[int]X{}
x[0] = map[int]X{}
x[0][9] = map[int]X{}
x[0][9][3] = map[int]X{}
x[0][4] = map[int]X{}
fmt.Println(x)
Output:
map[0:map[9:map[3:map[]] 4:map[]]]
If we want to test if there is a "value" based on a series of keys, we have 2 options: either use the special v, ok := m[i] indexing (which reports if a value for the specified key exists), or test if the value is not nil, e.g. m[i] != nil.
Let's see some examples testing the above built map:
var ok bool
_, ok = x[0][9][3]
fmt.Println("x[0][9][3] exists:", ok, "; alternative way:", x[0][9][3] != nil)
_, ok = x[0][9][4]
fmt.Println("x[0][9][4] exists:", ok, "; alternative way:", x[0][9][4] != nil)
_, ok = x[0][4]
fmt.Println("x[0][4] exists:", ok, "; alternative way:", x[0][4] != nil)
_, ok = x[0][4][9][9][9]
fmt.Println("x[0][4][9][9][9] exists:", ok, "; alternative way:", x[0][4][9][9][9] != nil)
Output:
x[0][9][3] exists: true ; alternative way: true
x[0][9][4] exists: false ; alternative way: false
x[0][4] exists: true ; alternative way: true
x[0][4][9][9][9] exists: false ; alternative way: false
Try these on the Go Playground.
Note: Even though x[0][4] is the last "leaf", indexing further like x[0][4][9][9][9] will not cause a panic as a nil map can be indexed and yields the zero value of the value type (which is nil in case the value type is a map type).
Ok I had some fun playing with this a bit. Here is a much better implementation than what I did before:
type mymap map[int]*myentry
type myentry struct {
m mymap
b bool
}
func (mm mymap) get(idx ...int) *myentry {
if len(idx) == 0 {
return nil
}
entry, ok := mm[idx[0]]
if !ok {
return nil
} else if len(idx) == 1 {
return entry
}
for i := 1; i < len(idx); i++ {
if entry == nil || entry.m == nil {
return nil
}
entry = entry.m[idx[i]]
}
return entry
}
func (mm mymap) setbool(v bool, idx ...int) {
if len(idx) == 0 {
return
}
if mm[idx[0]] == nil {
mm[idx[0]] = &myentry{m: make(mymap), b: false}
} else if mm[idx[0]].m == nil {
mm[idx[0]].m = make(mymap)
}
if len(idx) == 1 {
mm[idx[0]].b = v
return
}
entry := mm[idx[0]]
for i := 1; i < len(idx); i++ {
if entry.m == nil {
entry.m = make(mymap)
entry.m[idx[i]] = &myentry{m: make(mymap), b: false}
} else if entry.m[idx[i]] == nil {
entry.m[idx[i]] = &myentry{m: make(mymap), b: false}
}
entry = entry.m[idx[i]]
}
entry.b = v
}
func (m mymap) getbool(idx ...int) bool {
if val := m.get(idx...); val != nil {
return val.b
}
return false
}
func (m mymap) getmap(idx ...int) mymap {
if val := m.get(idx...); val != nil {
return val.m
}
return nil
}
Playground link
Something like that ought to get you started
If you don't need the hierarchical map structure and just want to use keys with variable length one approach could be to simply use strings as keys and one single map.
m := make(map[string]bool)
k := fmt.Sprintf("%v_%v_%v", 1, 2, 3)
m[k] = true
fmt.Println(m[k])
You cannot do this as this sort of type is not representable in Go's type system.
You will have to redesign.
E.g. a type arbitrarilyKeyedMapwith a method lookup(vals ...int) bool.
Probably you'll need methods for setting and deletion too.

Please explain &, and * pointers

There have been multiple instances where the compiler throws an error when I try to pass variables as arguments inside Go functions. I've been able to debug this sometimes by using a pointer in front of the variable. Both &, and * pointers seem to clear the error. Though, I'd like to understand why. I'm wondering what the difference between &, and * is, and when each should be used. Thank you!
func (ctx *NewContext) SendNotification(rw http.ResponseWriter, req *http.Request, p httprouter.Params) {
decoder := json.NewDecoder(req.Body)
var u User
if err := decoder.Decode(&u); err != nil {
http.Error(rw, "could not decode request", http.StatusBadRequest)
return
}
}
In your example above you defined u as type User, but not a pointer to a User. So you need the &u because the Decode function in the json package is expecting an address or pointer.
If you created the instance of User like this: u := new(User) it would be a pointer since the new function returns a pointer. You could also create a pointer to a user like this: var u *User. If you did either of those, you would have to take out the & in the call to Decode for it to work.
Pointers are basically variables that hold addresses. When you put the & in front of a variable it returns the address. The * could be read as 'redirect of'. So when you create a pointer like this:
var x *int
This can be read as x will redirect to an int. And when you assign a value to x you would give it an address like this:
y := 10
x = &y
Where y is some int. So if you were to print out x, you would get the address of y, but if you printed out *x you would redirect to the what x points to which is y's value which is 10. If you were to print out &x, you would get the address of the pointer, x, itself.
If you tried to print out *y, which is just an int, not a pointer, it would throw an error because you would be redirecting with some value that is not an address to redirect to.
Run the below for some pointer fun:
package main
import "fmt"
func main() {
var y int
var pointerToY *int
var pointerToPointerToInt **int
y = 10
pointerToY = &y
pointerToPointerToInt = &pointerToY
fmt.Println("y: ", y)
fmt.Println("pointerToY: ", pointerToY)
fmt.Println("pointerToPointerToInt: ", pointerToPointerToInt)
fmt.Println("&y: ", &y) // address of y
fmt.Println("&pointerToY: ", &pointerToY)// address of pointerToY
fmt.Println("&pointerToPointerToInt: ", &pointerToPointerToInt) // address of pointerToPointerToInt
// fmt.Println(*y) throws an error because
// you can't redirect without an address..
// y only has int value of 10
fmt.Println("*pointerToY: ", *pointerToY) // gives the value of y
fmt.Println("*pointerToPointerToInt: ", *pointerToPointerToInt) // gives the value of pointerToY which is the address of y
fmt.Println("**pointerToPointerToInt: ", **pointerToPointerToInt) // this gives 10, because we are redirecting twice to get y
if pointerToY == *pointerToPointerToInt {
fmt.Println("'pointerToY == *pointerToPointerToInt' are the same!")
}
if pointerToY == &y {
fmt.Println("'pointerToY == &y' are the same!")
}
if &pointerToY == pointerToPointerToInt {
fmt.Println("'&pointerToY == pointerToPointerToInt' are the same!")
}
if y == **pointerToPointerToInt {
fmt.Println("'y == **pointerToPointerToInt' are the same!")
}
if pointerToY == *pointerToPointerToInt {
fmt.Println("'pointerToY == *pointerToPointerToInt' are the same!")
}
}
Hope this helps!
I will quote one smart dude:
& in front of variable name is used to retrieve the address of where
this variable’s value is stored. That address is what the pointer is
going to store.
* in front of a type name, means that the declared variable will store an address of another variable of that type (not a value of that
type).
* in front of a variable of pointer type is used to retrieve a value stored at given address. In Go speak this is called dereferencing.
source: http://piotrzurek.net/2013/09/20/pointers-in-go.html
A simple example showing the code execution sequence.
import (
"fmt"
)
func main() {
x := 0
fmt.Println("Step 1", x)
foo(&x)
fmt.Println("Step 4", x)
}
func foo(y *int) {
fmt.Println("Step 2", *y)
*y = 100
fmt.Println("Step 3", *y)
}
/*
Steps Result
1 0
2 0
3 100
4 100
*/
pointer is used to point towards address and it stores the memory address
Adding one example to help understand pointer vs address:
Demo code
package main
import "fmt"
func main() {
var y int
var pointerToY *int
var x int
//var willThrowErrorVariable int
y = 10
pointerToY = &y
//willThrowErrorVariable = &y
x = *pointerToY
fmt.Println("y: ",y)
fmt.Println("y's address using pointerToY: ",pointerToY)
y = 4
fmt.Println("====================================================")
fmt.Println("Address of y after its value is changed: ",pointerToY)
fmt.Println("value of y using pointer after its value is changed: ",*pointerToY)
fmt.Println("Value of x after y value is changed: ",x)
}
output
y: 10
y's address using pointerToY: 0x414020
====================================================
Address of y after its value is changed: 0x414020
value of y using pointer after its value is changed: 4
Value of x after y value is changed: 10
As we can see, the value might change but the address(&) remains same and so the pointer(*) points to the value of address.
In above example,
pointerToY holds the pointer to refer address of y.
x holds the value which we pass to it using pointer to address of y.
After changing the value of y , the x still has 10 but if we try to access the value using pointer to address (pointerToY) , we get 4
For this answer I will try to explain it with a variable value. A pointer can point also to a struct value.
& returns a pointer, which points to a variable value.
* reads the variable value to which the pointer is pointing.
Example:
func zero(xPointer *int) {
*xPointer = 0
fmt.Println(*xPointer)
}
func main() {
x := 1
zero(&x)
fmt.Println(x) // x is 0
}
I would like to explain the concept of pointers(* and &) with an example:
Think of an example where we want to increment a variable by 1 with help of a function.
package main
import (
"fmt"
)
func main() {
x := 7
fmt.Print(inc(x))
}
func inc(x int) int {
return x + 1
}
Explanation of above: We have a function func inc(x int) int which takes an integer and returns an integer with performing an increment.
Note: Kindly pay attention that func inc(x int) int returns an int, Now what happens if we do not have a return type with that
function?? This is solved by the pointer.
Look at the below code:
package main
import (
"fmt"
)
func main() {
x := 7
inc(&x)
fmt.Print(x)
}
func inc(x *int) {
*x++
}
Explanation of the above code:
Now as our function func inc(x *int) does not have a return type we cannot get any incremented value from this function but what we can do is that we can send a location(address) to this function and tell it to increment the value at this location by one and now we can access that location from inside main() and our job is done.
A quick tip: * in front of a variable means what is stored in that variable?? and & in front of a variable means what is the internal address of that variable?

Declaring a pointer to a struct

I'm confused because there seem to be two ways to initialize a pointer to a struct in the go language and they appear to me to be somewhat opposite in logic.
var b *Vertex
var c &Vertex{3 3}
Why does one use a * and the other use a & if b and c have the same resulting type? My apologies for not adequately understanding the posts already up related to this topic.
I am also not yet straight on the implications of "receivers" in this context. The terminology I am familiar with is "reference to (a)" or "pointer to (a)" or "address of (a)" and "de-reference of" or "value at address".
Thanks in advance for your help.
There are a number of ways to declare a pointer to a struct and assign values to the struct fields. For example,
package main
import "fmt"
type Vertex struct {
X, Y float64
}
func main() {
{
var pv *Vertex
pv = new(Vertex)
pv.X = 4
pv.Y = 2
fmt.Println(pv)
}
{
var pv = new(Vertex)
pv.X = 4
pv.Y = 2
fmt.Println(pv)
}
{
pv := new(Vertex)
pv.X = 4
pv.Y = 2
fmt.Println(pv)
}
{
var pv = &Vertex{4, 2}
fmt.Println(pv)
}
{
pv := &Vertex{4, 2}
fmt.Println(pv)
}
}
Output:
&{4 2}
&{4 2}
&{4 2}
&{4 2}
&{4 2}
References:
The Go Programming Language Specification
Variable declarations
Short variable declarations
Address operators
Allocation
Composite literals
Receivers are used for methods. For example, v is the receiver for the Vertex Move Method.
package main
import "fmt"
type Vertex struct {
X, Y float64
}
func NewVertex(x, y float64) *Vertex {
return &Vertex{X: x, Y: y}
}
func (v *Vertex) Move(x, y float64) {
v.X = x
v.Y = y
}
func main() {
v := NewVertex(4, 2)
fmt.Println(v)
v.Move(42, 24)
fmt.Println(v)
}
Output:
&{4 2}
&{42 24}
References:
The Go Programming Language Specification
Method sets
Method declarations
Calls
Method expressions
Method values
var c = &Vertex{3, 3} (you do need the =) is declaring a struct and then getting the reference to it (it actually allocates the struct, then gets a reference (pointer) to that memory).
var b *Vertex is declaring b as a pointer to Vertex, but isn't initializing it at all. You'll have a nil pointer.
But yes, the types are the same.
You can also do:
var d *Vertex
d = &Vertex{3,3}
In addition to what Wes Freeman mentioned, you also asked about receivers.
Let say you have this:
type Vertex struct {
}
func (v *Vertex) Hello() {
... do something ...
}
The Vertex struct is the receiver for the func Hello(). So you can then do:
d := &Vertex{}
d.Hello()

Using a map for its set properties with user defined types

I'm trying to use the built-in map type as a set for a type of my own (Point, in this case). The problem is, when I assign a Point to the map, and then later create a new, but equal point and use it as a key, the map behaves as though that key is not in the map. Is this not possible to do?
// maptest.go
package main
import "fmt"
func main() {
set := make(map[*Point]bool)
printSet(set)
set[NewPoint(0, 0)] = true
printSet(set)
set[NewPoint(0, 2)] = true
printSet(set)
_, ok := set[NewPoint(3, 3)] // not in map
if !ok {
fmt.Print("correct error code for non existent element\n")
} else {
fmt.Print("incorrect error code for non existent element\n")
}
c, ok := set[NewPoint(0, 2)] // another one just like it already in map
if ok {
fmt.Print("correct error code for existent element\n") // should get this
} else {
fmt.Print("incorrect error code for existent element\n") // get this
}
fmt.Printf("c: %t\n", c)
}
func printSet(stuff map[*Point]bool) {
fmt.Print("Set:\n")
for k, v := range stuff {
fmt.Printf("%s: %t\n", k, v)
}
}
type Point struct {
row int
col int
}
func NewPoint(r, c int) *Point {
return &Point{r, c}
}
func (p *Point) String() string {
return fmt.Sprintf("{%d, %d}", p.row, p.col)
}
func (p *Point) Eq(o *Point) bool {
return p.row == o.row && p.col == o.col
}
package main
import "fmt"
type Point struct {
row int
col int
}
func main() {
p1 := &Point{1, 2}
p2 := &Point{1, 2}
fmt.Printf("p1: %p %v p2: %p %v\n", p1, *p1, p2, *p2)
s := make(map[*Point]bool)
s[p1] = true
s[p2] = true
fmt.Println("s:", s)
t := make(map[int64]*Point)
t[int64(p1.row)<<32+int64(p1.col)] = p1
t[int64(p2.row)<<32+int64(p2.col)] = p2
fmt.Println("t:", t)
}
Output:
p1: 0x7fc1def5e040 {1 2} p2: 0x7fc1def5e0f8 {1 2}
s: map[0x7fc1def5e0f8:true 0x7fc1def5e040:true]
t: map[4294967298:0x7fc1def5e0f8]
If we create pointers to two Points p1 and p2 with the same coordinates they point to different addresses.
s := make(map[*Point]bool) creates a map where the key is a pointer to the memory allocated to a Point and the value is boolean value. Therefore, if we assign elements p1 and p2 to the map s then we have two distinct map keys and two distinct map elements with the same coordinates.
t := make(map[int64]*Point) creates a map where the key is a composite of the coordinates of a Point and the value is a pointer to the Point coordinates. Therefore, if we assign elements p1 and p2 to the map t then we have two equal map keys and one map element with the shared coordinates.

Resources