Pointer Understanding [duplicate] - pointers

This question already has an answer here:
How to print the address of struct variable in go
(1 answer)
Closed 3 years ago.
I have struct type and referring address of the variable, but it does not reflect latest value of the variable in the defer function.
type XY struct {
S string
}
func CloseP(x *XY) {
if x != nil {
fmt.Println("Pointer-Closing", x.S)
}
}
func main() {
xp2 := &XY{"Pointer-X2 First"}
fmt.Println(xp2)
defer CloseP( xp2 )
xp2 = &XY{"Pointer-X2 Second"}
fmt.Println(xp2)
}
Output
&{Pointer-X2 First}
&{Pointer-X2 Second}
Pointer-Closing Pointer-X2 First
Expected Output
0xc000086018
0xc000086018
Pointer-Closing Pointer-X2 Second
My questions are:
Why is it display with '&' in the actual output, where it suppose to print address of the variable.
Why defer function is not reflecting latest value of the 'xp2' variable ?
So for the point 2- I have implemented below function. Can someone tell me is this best way to resolve this problem.
func main() {
xp2 := XY{"Pointer-X2 First"}
defer CloseP( &xp2 )
xp2 = XY{"Pointer-X2 Second"}
}
Output is
Pointer-Closing Pointer-X2 Second

Why is it display with '&' in the actual output, where it suppose to print address of the variable
Take a look at the format options here:
https://golang.org/pkg/fmt/
Println is using the default %v, if you want to print the value of the pointer, you can use the %p format, like so:
fmt.Printf("Pointer-Closing %p\n", xp2)
Why defer function is not reflecting latest value of the 'xp2' variable ?
Take a look here:
https://blog.golang.org/defer-panic-and-recover
A deferred function's arguments are evaluated when the defer statement is evaluated.
So at the time the defer is evaluated there, the pointer is referencing the first object, so that output is as expected.

Related

Initializing a map in a non-pointer type function in Go [duplicate]

This question already has answers here:
Why can't I append to a slice that's the property of a struct in golang?
(1 answer)
Golang Operator Overloading
(1 answer)
How to modify the value of a simple type through pointer receiver method in Go?
(2 answers)
Struct is empty after Json unmarshal when accessed by another package
(1 answer)
Remove an element of a slice in a struct [duplicate]
(1 answer)
Closed 2 years ago.
I'm sure there's a good explanation for this, but I've not been able to find it. Can anyone help me understand what is happening the following code example?
package main
import (
"fmt"
)
type work struct {
data map[string]string
}
func (w work) doSome() {
w.data = make(map[string]string)
w.data["k1"] = "v1"
}
func main() {
work := work{}
work.doSome()
if work.data == nil {
fmt.Println("data is nil")
} else {
fmt.Println("data is", work.data)
}
}
This prints out data is nil, which is not what I expected. If I rework this to be a pointer type (i.e. *work) for doSome method , it initializes the struct's variable. I'd like to understand why these are different. I assume it's something to do with map being a pointer, of sorts, but haven't been able to find a good reference to explain this.
Playground link - https://play.golang.org/p/lTN11TRkRNj
With a value receiver (func (w work) doSome()) the function gets a copy of the work struct. When it sets w.data, it is set for that copy, not for the instance of work declared in main.
Maps are essentially reference types, so if you initialized the map in main, this would've worked:
func (w work) doSome() {
w.data["k1"] = "v1"
}
func main() {
work := work{data:map[string]string{}}
work.doSome()
}
Or, you should use a pointer receiver, so the work declared in main is sent to doSome as a pointer:
func (w *work) doSome() {
w.data = make(map[string]string)
w.data["k1"] = "v1"
}
func main() {
work := work{}
work.doSome()
}

Confusion with pointer, slices and interface{} in function arguments in go

I've been reading about how Go passes arguments to functions via pointer vs. value. I've been reading about the interface type. And I've been tampering with the reflect package. But clearly, I still don't understand how it all works because of this example code here:
package main
import (
"reflect"
"fmt"
)
type Business struct {
Name string
}
func DoSomething(b []Business) {
var i interface{}
i = &b
v := reflect.ValueOf(i).Elem()
for c:=0 ;c<10; c++ {
z := reflect.New(v.Type().Elem())
s := reflect.ValueOf(z.Interface()).Elem()
s.Field(0).SetString("Pizza Store "+ fmt.Sprintf("%v",c))
v.Set(reflect.Append(v, z.Elem()))
}
fmt.Println(b)
}
func main() {
business := []Business{}
DoSomething(business)
}
When I run this code, it will print a list of ten Business structs with the Business.Name of Pizza 0 to 9. I understand that in my example, that my DoSomething function received a copy of the slice of business, and hence, the business variable in my main function remains unaffected by whatever DoSomething does.
What I did next was change my func DoSomething(b []Business) to func DoSomething(b interface{}). Now when I try to run my script, I get the run time error of panic: reflect: Elem of invalid type on on the line z := reflect.New(v.Type().Elem())
I noticed that with DoSomething(b []Business), the variable i == &[]. But with DoSomething(b interface{}), the variable i == 0xc42000e1d0. Why is the variable i different under these two circumstances?
Your debugger most likely uses (or at least follows) the default formatting rules of the fmt package:
For compound objects, the elements are printed using these rules, recursively, laid out like this:
struct: {field0 field1 ...}
array, slice: [elem0 elem1 ...]
maps: map[key1:value1 key2:value2 ...]
pointer to above: &{}, &[], &map[]
In your first case i holds a value of type *[]Business. So if a value being printed (or inspected) is a pointer to slice, it is printed as &[values].
In your second case i holds a pointer to an interface{} value, which is of type *interface{}. When printing a value of this type, the default %p format is used which simply prints the memory address as a hexadecimal value prefixed with 0x.

What does 'myVariable.(type)' return exactly?

I created a simple code
package main
import (
"fmt"
)
func main() {
a := 5
b := &a
Test(b)
fmt.Println(a)
fmt.Println(*b)
}
func Test(result interface{}){
switch r := result.(type) {
case *int:
*r = 10
}
}
You can run it here
In Test method inside switch statement I create new variable that is a type of my parameter.
Why does my variable 'b' update after update of this pointer. Why does this new variable points to the old one?
The result of program execution is
10
10
But expected
5
5
UPDATE
I'd like to precise the question. I did not assign my pointer to 'b' to variable 'r' in Test.
I expect that
r := result.(type)
gives me the type of the result. But why if I change value of a pointer of a new variable result is changed too
UPDATE 2
As suggested I checked again a specification and didn't found an answer. In the next construction
switch r := result.(type) {
case *int:
*r = 10
}
What does result.(type) return exactly?
A type switch compares types rather than values. It is otherwise similar > to an expression switch. It is marked by a special switch expression that > has the form of a type assertion using the reserved word type rather than > an actual type:
switch x.(type) {
// cases
}
See information on type assertions here and here.
There is a good description of pointers in go here.
In your code &a means the address of a and b returns a pointer to an int (*int).
In the Test function you are saying store the value 10 in the memory location pointed to by r.

How to get the pointer of return value from function call?

I just need a pointer to time.Time, so the code below seems invalid:
./c.go:5: cannot take the address of time.Now()
I just wonder why? Is there any way to do that except to do assignment to a variable first and take the pointer of the variable?
package main
import "time"
func main() {
_ = &time.Now()
}
The probably unsatisfying answer is "you can't do it because the spec says so." The spec says that to use & on something it has to be addressable or a compound literal, and to be addressable it has to be "a variable, pointer indirection, or slice indexing operation; or a a field selector of an addressable struct operand; or an array indexing operation of an addressable array." Function calls and method calls are definitely not on the list.
Practically speaking, it's probably because the return value of a function may not have a usable address; it may be in a register (in which case it's definitely not addressable) or on the stack (in which case it has an address, but one that won't be valid if it's put in a pointer that escapes the current scope. To guarantee addressability, Go would have to do pretty much the exact equivalent of assigning it to a variable. But Go is the kind of language that figures that if it's going to allocate storage for a variable it's going to be because you said to, not because the compiler magically decided to. So it doesn't make the result of a function addressable.
Or I could be over-thinking it and they simply didn't want to have a special case for functions that return one value versus functions that return multiple :)
You can't directly take the address of a function call (or more precisely the return value(s) of the function) as described by hobbs.
There is another way but it is ugly:
p := &[]time.Time{time.Now()}[0]
fmt.Printf("%T %p\n%v", p, p, *p)
Output (Go Playground):
*time.Time 0x10438180
2009-11-10 23:00:00 +0000 UTC
What happens here is a struct is created with a literal, containing one element (the return value of time.Now()), the slice is indexed (0th element) and the address of the 0th element is taken.
So rather just use a local variable:
t := time.Now()
p := &t
Or a helper function:
func ptr(t time.Time) *time.Time {
return &t
}
p := ptr(time.Now())
Which can also be a one-liner anonymous function:
p := func() *time.Time { t := time.Now(); return &t }()
Or as an alternative:
p := func(t time.Time) *time.Time { return &t }(time.Now())
For even more alternatives, see:
How do I do a literal *int64 in Go?
Also see related question: How can I store reference to the result of an operation in Go?
Fortunately, generics now offer quite a clean solution by defining a function only one time, that can be used on any type:
package main
func ptr[T any](x T) *T {
return &x
}
func main() {
print(ptr("foo"))
print(ptr(42))
}
Playground: https://go.dev/play/p/TgpEPKjpXX7
However, this will work only starting from Golang 1.18. For previous versions, you'll need a function for each type, as other answers suggested.
If you are having this trouble with a function you wrote, change your function to return a pointer. Even though you can't take the address of a return value, you can dereference a return value, so it will be suitable whether you want the pointer or the object.
func Add(x, y int) *int {
tmp := x + y
return &tmp
}
func main() {
fmt.Println("I want the pointer: ", Add(3, 4))
fmt.Println("I want the object: ", *Add(3, 4))
}
https://play.golang.org/p/RogRZDNGdmY

Passing a pointer inside a loop with anonymous go functions causes only last element pointer to be used

So in the following code I'm passing pointers to anonymous go functions but the code is not behaving as I am expecting it to do.
package main
import "fmt"
type (
Element struct{
Name string
}
)
func main() {
elements := []Element{{"first"}, {"second"}, {"third"}, {"fourth"}}
waiting := make(chan bool)
for _, element := range elements {
go func(element *Element){
fmt.Println("Element Name: ", element.Name)
waiting <- true
}(&element)
}
for i := 0; i < 4; i++{
<- waiting
}
}
I expected the code to write:
'first'
'second'
'third'
'fourth'
in any order but instead it is printing:
'fourth'
'fourth'
'fourth'
'fourth'
So it seems as the anonymous go function 'resolves' it's *Element parameter to whatever was in that loop at that time, so this code would be fixed by passing the Element{} itself instead of the pointer to the element.
My question is:
Is this defined behaviour?
How could i rewrite this to accept
pointers to my Element{}?
Playground:
http://play.golang.org/p/tcRvforQE4
Edit: question formatting
What happens is that the for loop places the value of elements[i] in the same element variable for each iteration, not creating a new one. This means that &element is always the same address (try printing it before calling the function!)
A simple solution would be to just pass it a pointer to the actual memeber of the slice:
for i := range elements {
go func(element *Element){
fmt.Println("PostStream: ", element.Name)
waiting <- true
}(&elements[i])
}

Resources