In Go, how do you assign a value returned by a function call to a pointer?
Consider this example, noting that time.Now() returns a time.Time value (not pointer):
package main
import (
"fmt"
"time"
)
type foo struct {
t *time.Time
}
func main() {
var f foo
f.t = time.Now() // Fail line 15
f.t = &time.Now() // Fail line 17
tmp := time.Now() // Workaround
f.t = &tmp
fmt.Println(f.t)
}
These both fail:
$ go build
# _/home/jreinhart/tmp/go_ptr_assign
./test.go:15: cannot use time.Now() (type time.Time) as type *time.Time in assignment
./test.go:17: cannot take the address of time.Now()
Is a local variable truly required? And doesn't that incur an unnecessary copy?
The local variable is required per the specification.
To get the address of a value, the calling function must copy the return value to addressable memory. There is a copy, but it's not extra.
Go programs typically work with time.Time values.
A *time.Time is sometimes used situations where the application wants to distinguish between no value and other time values. Distinguishing between a SQL NULL and a valid time is an example. Because the zero value for a time.Time is so far in the past, it's often practical to use the zero value to represent no value. Use the IsZero() method to test for a zero value.
Related
I have written the below code. I know that returning the address of a variable which was
created in a function is a wrong approach since the created local variable will be in stack, and
after completing the function the variable will be popped from stack.
I have created a person whose name is 'latif'. Then I have used changeName() function. It changes name field of the person struct as 'uluman'. It has returned the address of the local variable. After finishing the function, the local variable should be popped. Then I have called sum() function for guarenting that the stack will change (paremeters of sum function will pushed. With other words, the cell value x points in the memory should change ). So the x points somewhere in stack.
package main
import "fmt"
type Person struct{
name string
age int
}
func sum(a, b int)int{
return a+b
}
func (t Person ) changeName(value string)*Person{
t.name = value
return &t //Delibiratly the address of the local variable is returned
}
func main(){
t := Person{name : "latif" }
fmt.Println("Before" , t.name)
x := t.changeName("uluman")
_= sum(5,10)
fmt.Println("After" , x.name)
return
}
I have expected that the fmt.Println(x.name) should print something different from 'uluman' since the x points stack address and it has changed, but it has printed 'uluman'.
What is wrong in here?
It is called "escape analysis".
Go compiler tries to find out if the address of a variable "escapes" a function, and if it does, it allocates the variable in the heap instead of stack. In this case, it finds that the address of t escapes the changeName function, so it is allocated in the heap, not in the stack. That is the reason why your program works.
For instance, this is a common way to construct structs:
type X struct {
...
}
func NewX() *X {
a:=X{}
...
return &a
}
Here, a is allocated in the heap, not on stack because the compiler knows that a escapes the function.
The following is also valid:
func f() {
i:=0
go func() {
...
i++
...
}()
}
Above, i escapes f, because address of i is in the closure of the newly created goroutine. After f returns, i continues to live.
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.
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
I'm getting this return value from a function call in the "reflect" package:
< map[string]string Value >.
Wondering if I can access the actual map inside the return value and if so, how?
EDIT:
So this is where I'm making the call which returns the Value object.
It returns [< map[string]string Value >] to which I grab the first object in that array. However, I'm not sure how to convert [< map[string]string Value >] into a regular map.
view_args := reflect.ValueOf(&controller_ref).MethodByName(action_name).Call(in)
Most reflect Value objects can be converted back to a interface{} value using the .Interface() method.
After obtaining this value, you can assert it back to the map you want. Example (play):
m := map[string]int{"foo": 1, "bar": 3}
v := reflect.ValueOf(m)
i := v.Interface()
a := i.(map[string]int)
println(a["foo"]) // 1
In the example above, m is your original map and v is the reflected value. The interface value i, acquired by the Interface method is asserted to be of type map[string]int and this value is used as such in the last line.
To turn the value in a reflect.Value into an interface{}, you use iface := v.Interface(). Then, to access that, you use a type assertion or type switch.
If you know you're getting a map[string]string the assertion is simply m := iface.(map[string]string). If there's a handful of possibilities, the type switch to handle them all looks like:
switch item := iface.(type) {
case map[string]string:
fmt.Println("it's a map, and key \"key\" is", item["key"])
case string:
fmt.Println("it's a string:", item)
default:
// optional--code that runs if it's none of the above types
// could use reflect to access the object if that makes sense
// or could do an error return or panic if appropriate
fmt.Println("unknown type")
}
Of course, that only works if you can write out all the concrete types you're interested out in the code. If you don't know the possible types at compile time, you have to use methods like v.MapKeys() and v.MapIndex(key) to work more with the reflect.Value, and, in my experience, that involves a long time looking at the reflect docs and is often verbose and pretty tricky.
So I found some code that help me get started with reflection in Go (golang), but I'm having trouble getting a the underlying value so that I can basically create a map[string]string from a struct and it's fields.
Eventually, I'd like to make the result into a map[string]interface{}, but this one issue is kind of blocking me.
The code I have at the moment:
package main
import (
"fmt"
"reflect"
)
type Foo struct {
FirstName string `tag_name:"tag 1"`
LastName string `tag_name:"tag 2"`
Age int `tag_name:"tag 3"`
}
func inspect(f interface{}) map[string]string {
m := make(map[string]string)
val := reflect.ValueOf(f).Elem()
for i := 0; i < val.NumField(); i++ {
valueField := val.Field(i)
typeField := val.Type().Field(i)
f := valueField.Interface()
val := reflect.ValueOf(f)
m[typeField.Name] = val.String()
}
return m
}
func dump(m map[string]string) {
for k, v := range m {
fmt.Printf("%s : %s\n", k, v)
}
}
func main() {
f := &Foo{
FirstName: "Drew",
LastName: "Olson",
Age: 30,
}
a := inspect(f)
dump(a)
}
The output from running the code:
FirstName : Drew
LastName : Olson
Age : <int Value>
From what I understand the output for FirstName and LastName are actual reflect.Value objects but for strings the String() method on value just outputs the underlying String. I'd like to either get the int and change it into a string, but from the relfect package documentation I'm not immediately seeing how that's done.
Soo.... How do I get the underlying value from a reflect.Value in golang?
A good example of how to parse values is the fmt package. See this code.
Using the mentioned code to match your problem would look like this:
switch val.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
m[typeField.Name] = strconv.FormatInt(val.Int(), 10)
case reflect.String:
m[typeField.Name] = val.String()
// etc...
}
Basically you need to check for all available Kinds.
It looks like you're on the right track. The problem I see with your code is it makes assumptions about the values, meaning when do you call Elem() and how many times (to resolve pointers). In order to know this you need to look at the reflect.Kind. Is the value a reflect.Ptr? Then use Elem().
Once you have the value from val.Interface() / val.String() / val.Int() you can convert your values as needed. What you use is going to depend on reflect.Kind. To convert an int to/from string you need to use the strconv package.
The encoding/json and encoding/xml packages do this kind of work already. The source code provides some great examples. For example, take a look at copyValue in encoding/xml/read.go and marshalSimple in encoding/xml/marshal.go.
This should be easier to do with Go 1.5 (August 2015)
See review 8731 and commit 049b89d by Rob Pike (robpike):
fmt: treat reflect.Value specially - as the value it holds
This would allow you to print the actual value of a Reflect.Value() argument:
When a reflect.Value is passed to Printf (etc.), fmt called the String method, which does not disclose its contents.
To get the contents, one could call Value.Interface(), but that is illegal
if the Value is not exported or otherwise forbidden.
This CL improves the situation with a trivial change to the fmt package: when we see a reflect.Value as an argument, we treat it exactly as we treat a reflect.Value we make inside the package.
This means that we always print the contents of the Value as if that was the argument to Printf.
This is arguably a breaking change but I think it is a genuine improvement and no greater a break than many other tweaks we have made to formatted output from this package.
Another simple solution can be ,
flavorName = fmt.Sprintf("%v",strct)
" fmt.Sprintf() " will return the value which can be stored in a variable.