Declaring a pointer to a struct - pointers

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()

Related

How to convert interface{} to map

I am trying to create a function that could accept following
*struct
[]*struct
map[string]*struct
Here struct could be any struct not just a specific one.
Converting interface to *struct or []*struct is working fine.
But giving error for map.
After reflect it shows it is map[] but giving error when try to iterate over range.
Here is code
package main
import (
"fmt"
"reflect"
)
type Book struct {
ID int
Title string
Year int
}
func process(in interface{}, isSlice bool, isMap bool) {
v := reflect.ValueOf(in)
if isSlice {
for i := 0; i < v.Len(); i++ {
strct := v.Index(i).Interface()
//... proccess struct
}
return
}
if isMap {
fmt.Printf("Type: %v\n", v) // map[]
for _, s := range v { // Error: cannot range over v (type reflect.Value)
fmt.Printf("Value: %v\n", s.Interface())
}
}
}
func main() {
b := Book{}
b.Title = "Learn Go Language"
b.Year = 2014
m := make(map[string]*Book)
m["1"] = &b
process(m, false, true)
}
Is there any way to convert interface{} to map and iterate or get it's elements.
If the map value can be any type, then use reflect to iterate through the map:
if v.Kind() == reflect.Map {
for _, key := range v.MapKeys() {
strct := v.MapIndex(key)
fmt.Println(key.Interface(), strct.Interface())
}
}
playground example
If there's a small and known set of struct types, then a type switch can be used:
func process(in interface{}) {
switch v := in.(type) {
case map[string]*Book:
for s, b := range v {
// b has type *Book
fmt.Printf("%s: book=%v\n" s, b)
}
case map[string]*Author:
for s, a := range v {
// a has type *Author
fmt.Printf("%s: author=%v\n" s, a)
}
case []*Book:
for i, b := range v {
fmt.Printf("%d: book=%v\n" i, b)
}
case []*Author:
for i, a := range v {
fmt.Printf("%d: author=%v\n" i, a)
}
case *Book:
fmt.Ptintf("book=%v\n", v)
case *Author:
fmt.Printf("author=%v\n", v)
default:
// handle unknown type
}
}
You don't need reflect here. Try:
v, ok := in.(map[string]*Book)
if !ok {
// Can't assert, handle error.
}
for _, s := range v {
fmt.Printf("Value: %v\n", s)
}
Same goes for the rest of your function. It looks like you're using reflection when you would be better served by a type switch.
Alternatively, if you insist on using reflection here (which doesn't make a lot of sense) you can also use Value.MapKeys with the result from your ValueOf (see the answer https://stackoverflow.com/a/38186057/714501)
This may help:
b := []byte(`{"keyw":"value"}`)
var f interface{}
json.Unmarshal(b, &f)
myMap := f.(map[string]interface{})
fmt.Println(myMap)
Another way to convert an interface{} into a map with the package reflect is with MapRange.
I quote:
MapRange returns a range iterator for a map. It panics if v's Kind is
not Map.
Call Next to advance the iterator, and Key/Value to access each entry.
Next returns false when the iterator is exhausted. MapRange follows
the same iteration semantics as a range statement.
Example:
iter := reflect.ValueOf(m).MapRange()
for iter.Next() {
key := iter.Key().Interface()
value := iter.Value().Interface()
...
}

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

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)

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?

Iterate through a map of interface that contains different levels of maps

So lets say I have a map of interface like this:
c := map[string]interface{} {
"test": test,
"test2": test2,
}
Assuming that test is a map[string]map[string]map[string]string and test2 is map[string]string.
How would I create a for loop that would enumerate each index of the map and would enumerate through each index's map also?
So far I have gotten:
func sanitize_map(m map[string]interface{}) map[string]interface{} {
for k, v := range m {
//Here is where I want to enumerate through the map of k
}
return m
}
No need for reflection; use a type assertion and pass the value back to your sanitize function
func sanitizeMap(m map[string]interface{}) map[string]interface{} {
for k, v := range m {
_ = k
if v, ok := v.(map[string]interface{}); ok {
sanitizeMap(v)
}
}
return m
}
You can use reflect:
import "reflect"
func sanitize_map(m map[string]interface{}) map[string]interface{} {
for k, v := range m {
// Do something with the key k
kind := reflect.ValueOf(v).Kind()
if kind == reflect.Map {
// You have to be sure the value is of type map[string]interface{}
newValue := v.(map[string]interface{})
// recursively call sanitize
sanitize_map(newValue)
}
}
return m
}
The carveat is: every value in the map has to be either not a map (atom) or a map[string]interface{}. Note map[string]interface{} and map[string]map[string]interface{} are completely unrelated types, and you cannot use a type assertion of the second type on the first one.
However, you can put a map[string]map[string]string in a map[string]interface{}, like this:
innerMap1 := make(map[string]interface{})
// map to strings
innerMap1["a"] = "String 1"
innerMap2 := make(map[string]interface{})
// set mappings, maybe to other types
outerMap := make(map[string]interface{})
outerMap["ABC"] = innerMap1
outerMap["DEF"] = innerMap2
Now you can pass outerMap to the function, and reflect will automatically "strip" the layers of maps for you.

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