I have a data structure like this demo. As you can see, foo has an embedded pointer to bar:
type foo struct {
*bar
}
type bar struct {
S []byte
}
And I'm using the reflect package like this:
func test(x interface{}) {
var v = reflect.ValueOf(x)
if v.Kind() == reflect.Struct {
fmt.Println("was a struct")
// panic: reflect: call of reflect.Value.Elem on struct Value
// v = v.Elem()
// panic: reflect: call of reflect.Value.Field on ptr Value
v = v.FieldByName("S")
}
}
func main() {
var f foo
test(f)
fmt.Println(string(f.S))
}
So v.Kind() is recognized as a reflect.Struct, but if I try to treat it like a struct by using .FieldByName("S"), it panics because it thinks v is a ptr.
So then if I try to treat it like a ptr by calling .Elem(), it panics because it thinks v is a struct.
I've tried reflect.Indirect(), as well as a few other things, but I can't figure out how to get the field of an embedded pointer.
Is there a way to get the reflect.Value representation from an embedded pointer to a struct?
Demo: http://play.golang.org/p/n0eea6XW3I
EDIT: Also tried v = v.FieldByName("bar"), but got:
panic: runtime error: invalid memory address or nil pointer dereference
The first thing we need to realize is that the line var f foo is equivalent to f := foo{}. This initializes the internal field bar (of type *bar) to its zero value... nil. The behavior of embedded types and reflect seems to be that it treats the embedded type's fields as fields of the type itself. So when you request v.FieldByName("S") it's trying to find that field in f's member, bar, which is nil.
You're trying to do this (*f.bar).S. (In Go the explicit pointer dereference isn't needed, but it makes my point). Now the question is: if you change is to v.FieldByName("bar") why does it give an error? Same reason.
Look closely at the stack trace, the FieldByName line no longer crashes, the line that crashes is fmt.Println(string(f.S)). Again, semantically you're doing (*f.bar).S. But the member "bar" is nil, so you are, in fact, doing a nil pointer dereference.
You can fix both errors by changing var f foo to f := foo{&bar{}}.
i was getting this error " panic: reflect: call of reflect.Value.Elem on struct Value" bcz of this line "reflect.ValueOf(parameterName).Elem()"
1.When i am using Elem() in reflex ,it means parameterName inside valueOf() should be a pointer to structure
func Search(flight interface{}, key string) string {
val := reflect.ValueOf(flight).Elem()
for i := 0; i < val.NumField(); i++ {
valueField := val.Field(i)
typeField := val.Type().Field(i)
if key == strings.ToLower(typeField.Name) {
return valueField.Interface().(string)
}
}
return ""
}
Now while calling search function my call should be like this!
result := Search(&flights, key)
Related
I am studying reflect in Go and trying to implement function which get map and return another map, where keys will be values and values will be keys.
Example:
m := map[string]int{"one": 1, "two": 2}
fmt.Println(ReverseMap(m)) // {1: "one", 2: "two"}
Here is my code:
func ReverseMap(in interface{}) interface{} {
var out reflect.Value
v := reflect.ValueOf(in)
if v.Kind() == reflect.Map {
for idx, key := range v.MapKeys() {
value := v.MapIndex(key)
if idx == 0 {
mapType := reflect.MapOf(reflect.TypeOf(value), reflect.TypeOf(key))
out = reflect.MakeMap(mapType)
}
out.SetMapIndex(value, key)
}
}
return out
}
This code panic with error:
panic: reflect.Value.SetMapIndex: value of type int is not assignable to type reflect.Value
I think the reason of this error is the declaration of out variable, but I don't know how to declare it correctly, if I don't know the type of this variable.
How can I fix this error?
The key and value are of type reflect.Value, so passing them to reflect.TypeOf() will not return the type descriptors of the key and value types of the map (string and int), but instead the type descriptor of the reflect.Value type itself.
Instead simply call their Value.Type() method:
mapType := reflect.MapOf(value.Type(), key.Type())
With this it'll (almost) work and print (try it on the Go Playground):
map[1:one 2:two]
I wrote "almost" because you're returning a reflect.Value, not a map. But if a reflect.Value is passed to the fmt package, it prints the value wrapped inside it:
If the operand is a reflect.Value, the operand is replaced by the concrete value that it holds, and printing continues with the next rule.
So you should call Value.Interface() on out before returning it.
It's easier to return early if the kind is not map, so you can create the map right after that:
func ReverseMap(in interface{}) interface{} {
v := reflect.ValueOf(in)
if v.Kind() != reflect.Map {
return nil
}
mapType := reflect.MapOf(v.Type().Elem(), v.Type().Key())
out := reflect.MakeMap(mapType)
for _, key := range v.MapKeys() {
out.SetMapIndex(v.MapIndex(key), key)
}
return out.Interface()
}
Try this variant on the Go Playground.
Another approach may be using Value.MapRange():
for iter := v.MapRange(); iter.Next(); {
out.SetMapIndex(iter.Value(), iter.Key())
}
Try this variant on the Go Playground.
type BookInfo struct {
Meta *TableMeta
...
}
func (si *schemaInfo) getTabInfo(obj interface{}) (*tabInfo, error) {
typ := reflect.TypeOf(obj)
val := reflect.ValueOf(obj)
if typ.Kind() != reflect.Ptr {
return nil, errors.New("nborm.schemaInfo.getDBInfo() error: required a pointer")
}
meta := *(**TableMeta)(unsafe.Pointer(val.Pointer()))
...
}
getTabInfo() works well, but I want to know why val.Pointer() return a value of **TableMeta? Why not a *TableMeta?The document of reflect says,
Pointer returns v's value as a uintptr. It returns uintptr instead of
unsafe.Pointer so that code using reflect cannot obtain
unsafe.Pointers without importing the unsafe package explicitly. It
panics if v's Kind is not Chan, Func, Map, Ptr, Slice, or
UnsafePointer.
In my mind:
info := &BookInfo{}
val := reflect.ValueOf(info)
ptr := val.Pointer()
meta := (*TableMeta)(unsafe.Pointer(val.Pointer()))
should work, but infact when I called val.Pointer(), the returned value is the pointer of *TableMeta(**TableMeta).
The value you have is a pointer to a BookInfo struct, it is of type *BookInfo. And the type of BookInfo.Meta field is also a pointer, it is of type *TableMeta, thus a *BookInfo can then be looked at as **TableMeta, hence the "double" pointer.
It's true that the struct pointer points to its first field, but don't build on it. It's fragile. If you add a field before it, it'll break badly (which will only happen at runtime, no compile time messages due to package unsafe).
So if the value is of type *BookInfo, simply obtain that out of the reflect.Value wrapper, then you can refer to its field like value.Meta, which will be of type *TableMeta. Avoid using package unsafe, especially if it's not needed.
I thought this is a simple thing to do, but I was wrong. I can't pass integer as pointer to function using interface{}.
Example:
var test int
someChange(&test)
fmt.Printf("after function: %d", test)
func someChange(i interface{}) error{
newFunnyValue := 42
i = newFunnyValue
fmt.Printf("hello from someChange now value test is: %d" , i)
return nil //change gone ok, so nil
}
And result:
hello from someChange now value test is: 42
after function: 0
I read that interface{} is similar to void* so above code should work but it's not, why? I want to add that if I pass some object which is a struct, everything works good.
Do I have to wrap int in some struct?
Edit:
https://play.golang.org/p/rg1vabug0P
If you want to observe the change outside of the someChange() function (in the test variable), you must modify the pointed value (assign a new value to it). You're not doing that, you just assign a new value to the i parameter (which is a local variable inside someChange()).
You may obtain the *int pointer from the i interface variable using type assertion, and then you can assign a new value to the pointed value.
Example:
func someChange(i interface{}) error {
newFunnyValue := 42
if p, ok := i.(*int); ok {
*p = newFunnyValue
return nil //change gone ok, so nil
}
return errors.New("Not *int")
}
Testing it:
var test int
someChange(&test)
log.Printf("after function: %d", test)
Output (try it on the Go Playground):
2009/11/10 23:00:00 after function: 42
Note that wrapping the int value or the *int pointer in a struct is unnecessary and it wouldn't make a difference if you're not assigning a new value to the pointed object.
i is still of type interface{} within the func someChange(). You have to cast it during the assignment:
*i.(*int) = 42
I have a struct type with a *int64 field.
type SomeType struct {
SomeField *int64
}
At some point in my code, I want to declare a literal of this (say, when I know said value should be 0, or pointing to a 0, you know what I mean)
instance := SomeType{
SomeField: &0,
}
...except this doesn't work
./main.go:xx: cannot use &0 (type *int) as type *int64 in field value
So I try this
instance := SomeType{
SomeField: &int64(0),
}
...but this also doesn't work
./main.go:xx: cannot take the address of int64(0)
How do I do this? The only solution I can come up with is using a placeholder variable
var placeholder int64
placeholder = 0
instance := SomeType{
SomeField: &placeholder,
}
Note: the &0 syntax works fine when it's a *int instead of an *int64. Edit: no it does not. Sorry about this.
Edit:
Aparently there was too much ambiguity to my question. I'm looking for a way to literally state a *int64. This could be used inside a constructor, or to state literal struct values, or even as arguments to other functions. But helper functions or using a different type are not solutions I'm looking for.
The Go Language Specification (Address operators) does not allow to take the address of a numeric constant (not of an untyped nor of a typed constant).
The operand must be addressable, that is, either a variable, pointer indirection, or slice indexing operation; or a field selector of an addressable struct operand; or an array indexing operation of an addressable array. As an exception to the addressability requirement, x [in the expression of &x] may also be a (possibly parenthesized) composite literal.
For reasoning why this isn't allowed, see related question: Find address of constant in go. A similar question (similarly not allowed to take its address): How can I store reference to the result of an operation in Go?
0) Generic solution (from Go 1.18)
Generics are added in Go 1.18. This means we can create a single, generic Ptr() function that returns a pointer to whatever value we pass to it. Hopefully it'll get added to the standard library. Until then, you can use github.com/icza/gog, the gog.Ptr() function (disclosure: I'm the author).
This is how it can look like:
func Ptr[T any](v T) *T {
return &v
}
Testing it:
i := Ptr(2)
log.Printf("%T %v", i, *i)
s := Ptr("abc")
log.Printf("%T %v", s, *s)
x := Ptr[any](nil)
log.Printf("%T %v", x, *x)
Which will output (try it on the Go Playground):
2009/11/10 23:00:00 *int 2
2009/11/10 23:00:00 *string abc
2009/11/10 23:00:00 *interface {} <nil>
Your other options (prior to Go 1.18) (try all on the Go Playground):
1) With new()
You can simply use the builtin new() function to allocate a new zero-valued int64 and get its address:
instance := SomeType{
SomeField: new(int64),
}
But note that this can only be used to allocate and obtain a pointer to the zero value of any type.
2) With helper variable
Simplest and recommended for non-zero elements is to use a helper variable whose address can be taken:
helper := int64(2)
instance2 := SomeType{
SomeField: &helper,
}
3) With helper function
Note: Helper functions to acquire a pointer to a non-zero value are available in my github.com/icza/gox library, in the gox package, so you don't have to add these to all your projects where you need it.
Or if you need this many times, you can create a helper function which allocates and returns an *int64:
func create(x int64) *int64 {
return &x
}
And using it:
instance3 := SomeType{
SomeField: create(3),
}
Note that we actually didn't allocate anything, the Go compiler did that when we returned the address of the function argument. The Go compiler performs escape analysis, and allocates local variables on the heap (instead of the stack) if they may escape the function. For details, see Is returning a slice of a local array in a Go function safe?
4) With a one-liner anonymous function
instance4 := SomeType{
SomeField: func() *int64 { i := int64(4); return &i }(),
}
Or as a (shorter) alternative:
instance4 := SomeType{
SomeField: func(i int64) *int64 { return &i }(4),
}
5) With slice literal, indexing and taking address
If you would want *SomeField to be other than 0, then you need something addressable.
You can still do that, but that's ugly:
instance5 := SomeType{
SomeField: &[]int64{5}[0],
}
fmt.Println(*instance2.SomeField) // Prints 5
What happens here is an []int64 slice is created with a literal, having one element (5). And it is indexed (0th element) and the address of the 0th element is taken. In the background an array of [1]int64 will also be allocated and used as the backing array for the slice. So there is a lot of boilerplate here.
6) With a helper struct literal
Let's examine the exception to the addressability requirements:
As an exception to the addressability requirement, x [in the expression of &x] may also be a (possibly parenthesized) composite literal.
This means that taking the address of a composite literal, e.g. a struct literal is ok. If we do so, we will have the struct value allocated and a pointer obtained to it. But if so, another requirement will become available to us: "field selector of an addressable struct operand". So if the struct literal contains a field of type int64, we can also take the address of that field!
Let's see this option in action. We will use this wrapper struct type:
type intwrapper struct {
x int64
}
And now we can do:
instance6 := SomeType{
SomeField: &(&intwrapper{6}).x,
}
Note that this
&(&intwrapper{6}).x
means the following:
& ( (&intwrapper{6}).x )
But we can omit the "outer" parenthesis as the address operator & is applied to the result of the selector expression.
Also note that in the background the following will happen (this is also a valid syntax):
&(*(&intwrapper{6})).x
7) With helper anonymous struct literal
The principle is the same as with case #6, but we can also use an anonymous struct literal, so no helper/wrapper struct type definition needed:
instance7 := SomeType{
SomeField: &(&struct{ x int64 }{7}).x,
}
Use a function which return an address of an int64 variable to solve the problem.
In the below code we use function f which accepts an integer and
returns a pointer value which holds the address of the integer. By using this method we can easily solve the above problem.
type myStr struct {
url *int64
}
func main() {
f := func(s int64) *int64 {
return &s
}
myStr{
url: f(12345),
}
}
There is another elegant way to achieve this which doesn't produce much boilerplate code and doesn't look ugly in my opinion. In case I need a struct with pointers to primitives instead of values, to make sure that zero-valued struct members aren't used across the project, I will create a function with those primitives as arguments.
You can define a function which creates your struct and then pass primitives to this function and then use pointers to function arguments.
type Config struct {
Code *uint8
Name *string
}
func NewConfig(code uint8, name string) *Config {
return &Config{
Code: &code,
Name: &name,
}
}
func UseConfig() {
config := NewConfig(1, "test")
// ...
}
// in case there are many values, modern IDE will highlight argument names for you, so you don't have to remember
func UseConfig2() {
config := NewConfig(
1,
"test",
)
// ...
}
If you don't mind using third party libraries, there's the lo package which uses generics (go 1.18+) which has the .ToPtr() function
ptr := lo.ToPtr("hello world")
// *string{"hello world"}
I am trying to pass to a third-party package a variadic list of pointers to fields in a struct. The package accepts a variadic interface{} list ( func Persist(...interface) error ), where each of the interface values is a pointer to a variable. I created a function that mocks how the third-party library and prints out the Type and Kind of the pointers (called mockFunction below).
When I pass it the address of the struct variables in a non-variadic way, they have their primitive Types and Values within the mocked function using the reflect calls. However, when I pass them in a variadic way using expansion, they have Type: Type: reflect.Value and Kind: struct. The third-party package does not know how to handle them in this form.
I would like to figure out a way to call the third-party package with a slice of interface{} (e.g. inv := make([]interface{}, 3) and use variadic expansion on the call Persist(inv...) if at all possible.
Here is the code with a link to Go Playground below:
package main
import (
"fmt"
"reflect"
)
type Investment struct {
Price float64
Symbol string
Rating int64
}
func main() {
inv := Investment{Price: 534.432, Symbol: "GBG", Rating: 4}
s := reflect.ValueOf(&inv).Elem()
variableParms := make([]interface{}, s.NumField())
for i := 0; i < s.NumField(); i++ {
variableParms[i] = s.Field(i).Addr()
}
// non-variadic call
mockFunction(&inv.Price, &inv.Symbol, &inv.Rating)
//variadic call
mockFunction(variableParms...)
}
func mockFunction(values ...interface{}) {
for i, value := range values {
rv := reflect.ValueOf(value)
fmt.Printf("value %d has Type: %s and Kind %s\n", i, rv.Type(), rv.Kind())
}
}
Go Playground Link
When I run it with the non-variadic parameters, the call to mockFunction returns the native Types and Kinds and the third-party package processes them fine:
value 0 has Type: *float64 and Kind ptr
value 1 has Type: *string and Kind ptr
value 2 has Type: *int64 and Kind ptr
When I run it with the variadic parameters, the values are different and the third-party package does not know how to handle these types:
value 0 has Type: reflect.Value and Kind struct
value 1 has Type: reflect.Value and Kind struct
value 2 has Type: reflect.Value and Kind struct
Is there any way to structure the slice definition and the call to what is placed in to the slice so that it can be variadic expanded and look like passing the pointers to the struct fields in the non-variadic way?
Addr() returns the reflect Value for the field pointer. Call Ptr() on the value to get the actual pointer as an interface{}.
variableParms[i] = s.Field(i).Addr().Ptr()
playground
I think that perhaps Go's handling for this case has changed since 2014 - certainly the code above no longer works for me with Go 1.10...
However the following code works for me to create an appropriate []interface{} to use in the described way...
func settableSliceFromStruct(inStruct interface{}) ([]interface{}, error) {
t := reflect.TypeOf(inStruct)
if t.Kind() != reflect.Ptr {
return nil, errors.New("can only assign values with pointer to struct")
}
v := reflect.ValueOf(inStruct).Elem()
t = t.Elem()
dataColumns := make([]interface{}, 0, t.NumField())
for i := 0; i < t.NumField(); i++ {
if weWantToIncludeThis(t.Field(i)) {
dataColumns = append(dataColumns, v.Field(i).Addr().Interface())
}
}
return dataColumns, nil
}
The critical part here would be for your code to use:
variableParms[i] = s.Field(i).Addr().Interface()