I'm writing a program where I need to access a value of a pointer which is passed as an interface{}.
playground
package main
import (
"reflect"
)
type Test struct {
Names []string
}
func main() {
arr := []string{"a", "a", "a", "a", "a", "a"}
obj := new(Test)
obj.Names = arr
TestFunc(obj)
}
func TestFunc(obj interface{}){
rt := reflect.TypeOf(obj)
switch rt.Kind() {
case reflect.Struct:
return
case reflect.Ptr:
TestFunc(*obj) //<<--- There is the problem, cannot figure out how to access
//value of obj and *obj is not allowed here because of interface{} type.
}
}
This is just a sample from a much bigger program, but it is enough to explain my problem.
So the problem is, when I pass a pointer to TestFunc() I do not know how to reach its value inside function. Is it possible at all?
I need to do some stuff based on wether it is a pointer or not, so if I keep passing pointer recursively the program will fail. I need to get the value from the passed pointer(and pass forward value instead of pointer) but I am not sure if it is possible because I am dealing with a type interface{} and not a pointer and compiler does not know if it is going to be a pointer passed so it does not allow something like "*obj" to reach the value of it.
If you need to support arbitrary levels of pointers then you can use reflection to get the value object:
v:=reflect.ValueOf(obj)
for v.Kind() == reflect.Ptr {
v = v.Elem()
}
v.Interface()
However, this is quite unusual to actually need to do in practice.
For your function, this could work as something like:
func TestFunc(obj interface{}){
rv := reflect.ValueOf(obj)
switch rv.Kind() {
case reflect.Struct:
// code here
return
case reflect.Ptr:
TestFunc(rv.Elm().Interface())
}
}
Related
I have the following code and I want to use interfaces:
Current code:
import (
"github.com/dorzheh/deployer/ui/dialog_ui"
. "github.com/dorzheh/go-dialog"
)
// all methods in https://github.com/dorzheh/deployer/blob/master/ui/dialog_ui/dialog_ui.go#L28
type Pb struct {
sleep time.Duration
step int
}
type DialogUi struct {
*Dialog //The source is https://github.com/dorzheh/go-dialog/blob/master/dialog.go#L34
Pb *Pb
}
I am trying to implement interfaces this way:
import (
"testing"
// . "github.com/dorzheh/go-dialog"
//"github.com/dorzheh/deployer/ui/dialog_ui"
)
type PBifaceT interface {
Step() int
}
type TestDialogUiT struct {
Pb *PBifaceT
}
func TestUiValidateUser(t *testing.T) {
x := dialog_ui.TestDialogUiT{}
PbPb := ImplPBifaceT{}
x.Pb = PbPb
parentId := x.Pb.Step()
t.Logf(fmt.Sprintf("%v", parentId))
}
I've made a playground. As you can see it runs in the following error:
prog.go:23: cannot use PbPb (type ImplPBifaceT) as type *PBifaceT in assignment:
*PBifaceT is pointer to interface, not interface
prog.go:25: x.Pb.Step undefined (type *PBifaceT is pointer to interface, not interface)
I tried to convert them in this playground:
func NewD() *PBifaceT {
// var err error
var res =new(ImplPBifaceT)
return (*PBifaceT)(res)
}
func main() {
x := TestDialogUiT{}
x.Pb = NewD()
parentId := x.Pb.Step()
fmt.Sprintf("%v", parentId)
}
The issue:
prog.go:23: cannot convert res (type *ImplPBifaceT) to type *PBifaceT
prog.go:30: x.Pb.Step undefined (type *PBifaceT is pointer to interface, not interface)
Are you sure you need your Pb field as a *PBifaceT.
If you keep it as a
type TestDialogUiT struct {
Pb *PBifaceT
}
and you do
x := TestDialogUiT{}
PbPb := ImplPBifaceT{}
x.Pb = PBifaceT(PbPb)
parentId := x.Pb.Step()
fmt.Printf("%v", parentId)
It works properly..
Take a look at this playground and see if it can help.
I'd suggest you to take a look at this tutorial and this doc.
I'd suggest you also to read this SO answer which explains a bit of how you shouldn't want to use interface pointers.
Background: In Go you pass around a pointer to something because of two reasons:
1) You want because your struct is really large and you want to avoid copying
2) you need to because the calee wants to modify the original (this is typical for methods with a pointer receiver). Now an interface value is really tiny (just two words) so reason 1 to pass a pointer to an interface value does not apply.
Reason 2 does not apply in most cases as passing a pointer to an interface value will allow you to change the interface value itself, but most often you would like to modify the value stored inside the interface value. This value stored inside the interface value often is a pointer value which allows to change the value of a struct by calling methods on an interface value which wrapps a pointer to this struct. This sounds complicated but isn't: The novice Go programmer just doesn't use pointers to interfaces (as this won't do any good) and the experienced Go programmer doesn't use pointers to interfaces (as it won't do much good) unless he needs to modify an interface value, typically during reflection.
You can use Pb by link, you were just missing pointer reference while assigning.
package main
import (
"fmt"
)
type PBifaceT interface {
Step() int
}
type TestDialogUiT struct {
Pb PBifaceT
}
type ImplPBifaceT struct {
}
func (m *ImplPBifaceT) Step() int {
return 0
}
func main() {
x := TestDialogUiT{}
PbPb := &ImplPBifaceT{}
x.Pb = PbPb
parentId := x.Pb.Step()
fmt.Printf("%v", parentId)
}
Please refer this playground link: https://play.golang.org/p/N7quQFpYU0
Changes were at line 12, 17, 23 & 27.
Do not use pointer to interface unless you are sure that's what you want, see Pb *PBifaceT inside TestDialogUiT. If you change it to just Pb PBifaceT your playground link just works.
An interface is already a pointer.
Is there a reason why I should create a struct using &StructName{} instead of Struct{}? I see many examples using the former syntax, even in the Effective Go Page but I really can not understand why.
Additional Notes:
I'm not sure whether I explained my problem well with these two approaches so let me refine my question.
I know that by using the & I will recieve a pointer instead of a value however I would like to know why would I use the &StructName{} instead of the StructName{}. For example, is there any benefits of using:
func NewJob(command string, logger *log.Logger) *Job {
return &Job{command, logger}
}
instead of:
func NewJob(command string, logger *log.Logger) Job {
return Job{command, logger}
}
Well, they will have different behavior. Essentially if you want to modify state using a method on a struct, then you will need a pointer, otherwise a value will be fine. Maybe an example will be better:
package main
import "fmt"
type test_struct struct {
Message string
}
func (t test_struct)Say (){
fmt.Println(t.Message)
}
func (t test_struct)Update(m string){
t.Message = m;
}
func (t * test_struct) SayP(){
fmt.Println(t.Message)
}
func (t* test_struct) UpdateP(m string) {
t.Message = m;
}
func main(){
ts := test_struct{}
ts.Message = "test";
ts.Say()
ts.Update("test2")
ts.Say() // will still output test
tsp := &test_struct{}
tsp.Message = "test"
tsp.SayP();
tsp.UpdateP("test2")
tsp.SayP() // will output test2
}
And you can run it here go playground
Assuming you know the general difference between a pointer and a value:
The first way allocates a struct and assigns a pointer to that allocated struct to the variable p1.
p1 := &StructName{}
The second way allocates a struct and assigns a value (the struct itself) to the variable s.
Then a pointer to that struct may be assigned to another variable (p2 in the following example).
s := StructName{}
p2 := &s
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 have the function below which accepts a bool pointer. I'm wondering if there is any notation which allows me to set the value of the is field to true in the struct literal; basically without to define a new identifier (i.e. var x := true ; handler{is: &x} )
package main
import "fmt"
func main() {
fmt.Println("Hello, playground")
check(handler{is: new(bool) })
}
type handler struct{
is *bool
}
func check(is handler){}
You can do that but it's not optimal:
h := handler{is: &[]bool{true}[0]}
fmt.Println(*h.is) // Prints true
Basically it creates a slice with one bool of value true, indexes its first element and takes its address. No new variable is created, but there is a lot of boilerplate (and backing array will remain in memory until the address to its first element exists).
A better solution would be to write a helper function:
func newTrue() *bool {
b := true
return &b
}
And using it:
h := handler{is: newTrue()}
fmt.Println(*h.is) // Prints true
You can also do it with a one-liner anonymous function:
h := handler{is: func() *bool { b := true; return &b }()}
fmt.Println(*h.is) // Prints true
Or a variant:
h := handler{is: func(b bool) *bool { return &b }(true)}
To see all your options, check out my other answer: How do I do a literal *int64 in Go?
This simplest way is to write a short function to turn a bool into a *bool.
func BoolPointer(b bool) *bool {
return &b
}
h := handler{is: BoolPointer(true)}
No.
There is no syntax to define a pointer to a primitive type, other than the zero value returned by new. The same goes for numeric types, and strings.
You either need to create a value before hand to take the address of, or you create the pointer with a zero value, and assign a new value after the fact.
I used a function similar to #icza but in a way more convenient (for me)
I created a BoolAddr function in my utils package
package utils
func BoolAddr(b bool) *bool {
boolVar := b
return &boolVar
}
For me it's easier to use
package main
import "example.com/example/utils"
...
type Example struct {
isActive *bool
}
ex := Expample {
isActive: utils.BoolAddr(true)
}
...
One of the reasons why pointers are helpful in go or any language for that matter, is they help us to "pass by reference". So if we pass anything by reference we can then "change" that thing. A function which takes a pointer to bool, can change the bool's value effectively even after the function returns. This is the very thing we do not want with constants, ie. their values should not change. Hence this restriction makes sense.
Apart from the tricks mentioned by icza above, would want to add a point here. Mostly we use pointers to bools rather than bools directly in order to use the nil value of pointers effectively, which otherwise have to be either true or false. If that IS the case, then you might want to use optional bool flags directly in the functions, rather than have pointers to bool or even a struct wrapping the single bool pointer as shown in your example, doing away with the complete requirement of a struct even.. Now, of course if the struct is reqd for any other reason, you can very well use any of the tricks by icza above.
Btw, you can directly have a copy of the bool value for using the adress of as below as well.
const check = true
chk := check
fmt.Println(&chk) // will give you the address of chk
chk = false
fmt.Println(chk) // will print false
fmt.Println(check) // will print true
So let's say that we have a function of the following form:
func WorkMagic(obj interface{}) interface{} {
switch t := obj.(type) {
case string:
// Do string magic
default:
// Do slice magic
}
...
}
I am expecting obj to be either a string or a slice, which I can ascertain via the switch. In the case of a slice, I want to be able to do ordering work on any arbitrary slice, regardless of type. Seems like the best way to accomplish this is using the unsafe package in a similar fashion to that discussed in this article.
Here however, the function accepts a specific type of slice ([]string), whereas I would like to be able to work on any slice. So the question is, given that I am accepting an empty interface as input, how might I access the underlying slice / array using unsafe.Pointer so as to be able to loop through and modify which value is associate with which index?
You'll want to use reflection. It enables you to work generically without giving up type and memory safety like unsafe would. Read the Go blog's Laws of Reflection.
func actOnSlices(i interface{}) {
v := reflect.ValueOf(i)
for v.Kind() == reflect.Ptr { // dereference pointers
v = v.Elem()
}
if v.Kind() != reflect.Slice { // ensure you actually got a slice
panic("given argument is not a slice")
}
// do slice stuff
}
Edit to answer your second question:
Yes – this can be done: elements of a slice are adressable and hence settable. See the following working example:
package main
import (
"fmt"
"reflect"
)
func main() {
s := []string{"foo", "bar"}
fmt.Println(swapIndexes(s, 0, 1)) // prints [bar foo]
}
func swapIndexes(i interface{}, x, y int) interface{} {
v := reflect.ValueOf(i)
for v.Kind() == reflect.Ptr { // dereference pointers
v = v.Elem()
}
if v.Kind() != reflect.Slice { // ensure you actually got a slice
panic("given argument is not a slice")
}
t := v.Index(x).Interface()
v.Index(x).Set(v.Index(y))
v.Index(y).Set(reflect.ValueOf(t))
return v.Interface()
}
Edit to answer your third question:
The unsafe package is not something you'll encounter much in user-land code. It exists to implement certain features (e.g. reflection, C interaction) that need to circumvent Go's safety guarantees to work. Using unsafe is unsafe, as the name suggests, because you can mess up big time without even realizing. By using unsafe, you're incurring in a big trade-off, so it better be worth it. Quoting #twotwotwo:
The downside of unsafe is that if you mess up you're in the old days of segfaults, memory corruption, and buffer-overflow security holes.
Also, as #twotwotwo suggested; it's more "Go-like" to repeat code than using reflection to achieve genericity.
To Go's type-system, []string and []int are two completely separate and unrelated types. just as int and string would be. The relation (both are slices) is obvious only to the programmer. There is no way of expressing "a slice" without saying a slice of what.