I'm trying to assign a value to a struct member that is a pointer, but it gives "panic: runtime error: invalid memory address or nil pointer dereference" at runtime...
package main
import (
"fmt"
"strconv"
)
// Test
type stctTest struct {
blTest *bool
}
func main() {
var strctTest stctTest
*strctTest.blTest = false
fmt.Println("Test is " + strconv.FormatBool(*strctTest.blTest))
}
The runtime error seems to come from the assignment of the value with *strctTest.blTest = false , but why? How do I set it to false?
Why is it an error? Because a pointer only points. It doesn't create anything to point AT. You need to do that.
How to set it to false? This all depends on WHY you made it a pointer.
Is every copy of this supposed to point to the same bool? Then it should be allocated some space in a creation function.
func NewStruct() *strctTest {
bl := true
return &strctTest{
blTest: &bl,
}
}
Is the user supposed to point it at a boolean of his own? Then it should be set manually when creating the object.
func main() {
myBool := false
stctTest := strctTest{
blTest: &myBool
}
fmt.Println("Test is " + strconv.FormatBool(*strctTest.blTest))
}
Another way you can think of it is the zero value of a boolean is false.
This is not as clear but another way to do it.
https://play.golang.org/p/REbnJumcFi
I would recommend a New() func that returns a reference to a initialized struct type.
You could also do something like:
package main
import (
"fmt"
"strconv"
)
// Test
type stctTest struct {
blTest *bool
}
func main() {
strctTest := stctTest{
blTest: &[]bool{true}[0],
}
fmt.Println("Test is " + strconv.FormatBool(*strctTest.blTest))
}
https://play.golang.org/p/OWSosQhrUql
Following up on JTs Answer, I also would recommend using the new function as such:
package main
import (
"fmt"
"strconv"
)
// Test
type stctTest struct {
blTest *bool
}
func main() {
strctTest := &stctTest{
blTest: new(bool),
}
*strctTest.blTest = true
fmt.Println("Test is " + strconv.FormatBool(*strctTest.blTest))
}
After initializing the memory with new(), you can directly assign a value to the de-referenced pointer. This way you do not need to use another variable to get the address from.
https://go.dev/play/p/BmekoTalQVh
Related
How come this program prints nil instead of hello? How can I solve this situation and successfully store that pointer in the struct? Shouldn't Go be able to figure out when local pointers are used outside the scope of a function?
package main
import (
"fmt"
)
type test struct {
name *string
}
func (t test) test() {
h := "hello"
t.name = &h
return
}
func main() {
a := test{nil}
a.test()
fmt.Println(a.name)
}
Your test function has a value receiver. So test will be applied on a copy of a. If you want to mutate a struct with a method, you should write a method which has a pointer receiver. On calling the method, go will automatically use the reference for this method
func (t *test) test() {
h := "hello"
t.name = &h
}
Is it possible to get the address of a function reference in Go?
Something like
func myFunction() {
}
// ...
unsafe.Pointer(&myFunction)
Just that is does not work that way. My guess it's not possible, but I did not found any proof yet.
Edit: Background
The background of my question comes from dealing with CGO and C Function pointers.
This works:
/*
void go_myFunction();
typedef void (*myFunction_f)();
myFunction_f pMyFunction;
*/
import "C"
//export go_myFunction
func go_myFunction() {
// ...
}
func SetupFp() {
C.pMyFunction = (*[0]byte)(unsafe.Pointer(C.go_myFunction))
}
I'm also aware that the documentation states that passing a pointer to a go function does not work. But the above code seems no to be that far from it. I was just wondering if one could somehow skip the export step.
function type in Go is not addressable and not comparable because:
Function pointers denote the code of the function. And the code of an anonymous function created by function literal is only stored once in memory, no matter how many times the code that returns the anonymous function value runs.
Original answer
If you need to compare addresses of a functions you can do it with reflect.Pointer. But any way this operation is more senseless than impossible because:
If v's Kind is Func, the returned pointer is an underlying code pointer, but not necessarily enough to identify a single function uniquely. The only guarantee is that the result is zero if and only if v is a nil func Value.
You may get the address of a Go function like this:
package main
import (
"fmt"
"reflect"
)
func HelloWorld() {
fmt.Println("Hello, world!")
}
func main() {
var ptr uintptr = reflect.ValueOf(HelloWorld).Pointer()
fmt.Printf("0x%x", ptr)
}
You can get address of function use function GetFuncAddr:
package main
import (
"fmt"
"unsafe"
"reflect"
)
func HelloWorld() {
fmt.Println("Hello, world!")
}
func GetFuncAddr(i interface{}) uintptr {
type IHeader struct {
typ uintptr
word uintptr
}
return (*IHeader)(unsafe.Pointer(&i)).word
}
func main() {
tmp := HelloWorld
ptr1 := *(*uintptr)(unsafe.Pointer(&tmp)) //Way 1
ptr2 := GetFuncAddr(HelloWorld) //Way 2
fmt.Printf("0x%x = 0x%x", ptr1, ptr2)
//Thits is not are functon addrress!!!
BadPTR1 := reflect.ValueOf(HelloWorld).Pointer()
BadPTR2 := **(**uintptr)(unsafe.Pointer(&tmp)) //dereferenced pointer
fmt.Printf("\nBAD: 0x%x = 0x%x", BadPTR1 , BadPTR2 )
}
I'm trying to retrieve the string value from a reflect.Value,
I expect value.String() to be okok but I got <interface {} Value> instead.
Did I miss something?
package main
import (
"fmt"
"reflect"
)
func dump(args *[]interface{}) {
value := reflect.ValueOf(*args).Index(0)
fmt.Println(value.String())
if value.String() != "okok" {
fmt.Println("miss")
}
}
func main () {
var args []interface{}
args = append(args, "okok")
dump(&args)
}
The documentation for Value.String explains the behavior:
Unlike the other getters, it does not panic if v's Kind is not String.
Instead, it returns a string of the form "<T value>" where T is v's
type.
String is just an implementation of the fmt.Stringer interface.
If you want the value itself, you can use the Interface function on reflect.Value and then do a type assertion to get the string. Example:
package main
import (
"fmt"
"reflect"
)
func dump(args *[]interface{}) {
value := reflect.ValueOf(*args).Index(0)
str := value.Interface().(string)
fmt.Println(str)
if str != "okok" {
fmt.Println("miss")
}
}
func main() {
var args []interface{}
args = append(args, "okok")
dump(&args)
}
Playground link
I need to know the type name and its path using reflection. type Type has a Name() and PkgPath() method but both of them return empty if the type is an interface.
However if I reflect a function and extract the type information of its arguments I get the correct type information. Should I assume it's a bug in the former case? Shouldn't TypeOf return the same type information regardless the context(e.g. type function parameter or type of a value) ?
I'm aware of type assertion but I don't always have a value to do the assertion so I need to work with reflect.Type information.
package main
import (
"fmt"
"reflect"
"golang.org/x/net/context"
)
func main() {
c := reflect.TypeOf(withValue(""))
fn := func(context.Context){}
fc := reflect.TypeOf(fn).In(0)
fmt.Println(isContext(c), isContext(fc), c, fc)
}
func isContext(r reflect.Type) bool {
return r.PkgPath() == "golang.org/x/net/context" && r.Name() == "Context"
}
func withValue(v interface{}) context.Context {
return context.WithValue(context.TODO(), "mykey", v)
}
Prints
false true *context.valueCtx context.Context
Here is some working code: https://play.golang.org/p/ET8FlguA_C
package main
import (
"fmt"
"reflect"
)
type MyInterface interface {
MyMethod()
}
type MyStruct struct{}
func (ms *MyStruct) MyMethod() {}
func main() {
var structVar MyInterface = &MyStruct{}
c := reflect.TypeOf(structVar)
fn := func(MyInterface) {}
fc := reflect.TypeOf(fn).In(0)
fmt.Println(isMyInterface(c), isMyInterface(fc), c, fc)
// OP expects : "true true main.MyInterface main.MyInterface"
}
func isMyInterface(r reflect.Type) bool {
// TypeOf trick found at https://groups.google.com/forum/#!topic/golang-nuts/qgJy_H2GysY
return r.Implements(reflect.TypeOf((*MyInterface)(nil)).Elem())
}
Here is my answer before I found an actual solution with reflect.
I'm gonna let it here because I think it still has some interesting parts.
First things first: for c, r.PkgPath() and r.Name() are empty because the underlying type is a pointer (*context.valueCtx).
To fix that, you can use c := reflect.Indirect(reflect.ValueOf(withValue(""))).Type()
But that does not make isContext(c) true, because you then have r.PkgPath() == "golang.org/x/net/context" && r.Name() == "valueCtx".
The best way to check if a var implements an interface is to drop the reflection and use a type assertion like this:
https://play.golang.org/p/td1YaHHej9
package main
import "fmt"
type MyInterface interface {
MyMethod()
}
type MyStruct struct{}
func (ms *MyStruct) MyMethod() {}
func main() {
var structVar MyInterface = &MyStruct{}
fmt.Println(isMyInterface(structVar))
}
func isMyInterface(object interface{}) bool {
_, ok := object.(MyInterface)
return ok
}
Your code works as you expect with the function parameter because there is no underlying value, so reflect uses the interface type. But for any concrete var, it will use the actual type of the value.
There are two kinds of Interface in golang, aka, eface and iface. And the eface is an empty interface, which can simply represented as interface {}. The iface is kind of interface which has at least one method, such as:
type MyInterface interface {
Greeting() string
}
In golang implementation, both eface and iface are two-word long struct. The eface holds the data and the data type, the iface holds the data, the interfacetype and the data type. When an iface assigned to an eface, the interfacetype information is ignored. Only the data and the data type passed to the eface.
So, reflect.TypeOf(i interface{}) 's parameter is and eface, no interfacetype information (aka context.Context in your case). So you can't get the original interfacetype.
I want to convert a struct to map in Golang. It would also be nice if I could use the JSON tags as keys in the created map (otherwise defaulting to field name).
Edit Dec 14, 2020
Since structs repo was archived, you can use mapstructure instead.
Edit TL;DR version, Jun 15, 2015
If you want the fast solution for converting a structure to map, see the accepted answer, upvote it and use that package.
Happy coding! :)
Original Post
So far I have this function, I am using the reflect package but I don't understand well how to use the package, please bear with me.
func ConvertToMap(model interface{}) bson.M {
ret := bson.M{}
modelReflect := reflect.ValueOf(model)
if modelReflect.Kind() == reflect.Ptr {
modelReflect = modelReflect.Elem()
}
modelRefType := modelReflect.Type()
fieldsCount := modelReflect.NumField()
var fieldData interface{}
for i := 0; i < fieldsCount; i++ {
field := modelReflect.Field(i)
switch field.Kind() {
case reflect.Struct:
fallthrough
case reflect.Ptr:
fieldData = ConvertToMap(field.Interface())
default:
fieldData = field.Interface()
}
ret[modelRefType.Field(i).Name] = fieldData
}
return ret
}
Also I looked at JSON package source code, because it should contain my needed implementation (or parts of it) but don't understand too much.
I also had need for something like this. I was using an internal package which was converting a struct to a map. I decided to open source it with other struct based high level functions. Have a look:
https://github.com/fatih/structs
It has support for:
Convert struct to a map
Extract the fields of a struct to a []string
Extract the values of a struct to a []values
Check if a struct is initialized or not
Check if a passed interface is a struct or a pointer to struct
You can see some examples here: http://godoc.org/github.com/fatih/structs#pkg-examples
For example converting a struct to a map is a simple:
type Server struct {
Name string
ID int32
Enabled bool
}
s := &Server{
Name: "gopher",
ID: 123456,
Enabled: true,
}
// => {"Name":"gopher", "ID":123456, "Enabled":true}
m := structs.Map(s)
The structs package has support for anonymous (embedded) fields and nested structs. The package provides to filter certain fields via field tags.
From struct to map[string]interface{}
package main
import (
"fmt"
"encoding/json"
)
type MyData struct {
One int
Two string
Three int
}
func main() {
in := &MyData{One: 1, Two: "second"}
var inInterface map[string]interface{}
inrec, _ := json.Marshal(in)
json.Unmarshal(inrec, &inInterface)
// iterate through inrecs
for field, val := range inInterface {
fmt.Println("KV Pair: ", field, val)
}
}
go playground here
Here is a function I've written in the past to convert a struct to a map, using tags as keys
// ToMap converts a struct to a map using the struct's tags.
//
// ToMap uses tags on struct fields to decide which fields to add to the
// returned map.
func ToMap(in interface{}, tag string) (map[string]interface{}, error){
out := make(map[string]interface{})
v := reflect.ValueOf(in)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
// we only accept structs
if v.Kind() != reflect.Struct {
return nil, fmt.Errorf("ToMap only accepts structs; got %T", v)
}
typ := v.Type()
for i := 0; i < v.NumField(); i++ {
// gets us a StructField
fi := typ.Field(i)
if tagv := fi.Tag.Get(tag); tagv != "" {
// set key of map to value in struct field
out[tagv] = v.Field(i).Interface()
}
}
return out, nil
}
Runnable example here.
Note, if you have multiple fields with the same tag value, then you will obviously not be able to store them all within a map. It might be prudent to return an error if that happens.
I like the importable package for the accepted answer, but it does not translate my json aliases. Most of my projects have a helper function/class that I import.
Here is a function that solves my specific problem.
// Converts a struct to a map while maintaining the json alias as keys
func StructToMap(obj interface{}) (newMap map[string]interface{}, err error) {
data, err := json.Marshal(obj) // Convert to a json string
if err != nil {
return
}
err = json.Unmarshal(data, &newMap) // Convert to a map
return
}
And in the main, this is how it would be called...
package main
import (
"fmt"
"encoding/json"
"github.com/fatih/structs"
)
type MyStructObject struct {
Email string `json:"email_address"`
}
func main() {
obj := &MyStructObject{Email: "test#test.com"}
// My solution
fmt.Println(StructToMap(obj)) // prints {"email_address": "test#test.com"}
// The currently accepted solution
fmt.Println(structs.Map(obj)) // prints {"Email": "test#test.com"}
}
package main
import (
"fmt"
"reflect"
)
type bill struct {
N1 int
N2 string
n3 string
}
func main() {
a := bill{4, "dhfthf", "fdgdf"}
v := reflect.ValueOf(a)
values := make(map[string]interface{}, v.NumField())
for i := 0; i < v.NumField(); i++ {
if v.Field(i).CanInterface() {
values[v.Type().Field(i).Name] = v.Field(i).Interface()
} else {
fmt.Printf("sorry you have a unexported field (lower case) value you are trying to sneak past. I will not allow it: %v\n", v.Type().Field(i).Name)
}
}
fmt.Println(values)
passObject(&values)
}
func passObject(v1 *map[string]interface{}) {
fmt.Println("yoyo")
}
I'm a bit late but I needed this kind of feature so I wrote this. Can resolve nested structs. By default, uses field names but can also use custom tags. A side effect is that if you set the tagTitle const to json, you could use the json tags you already have.
package main
import (
"fmt"
"reflect"
)
func StructToMap(val interface{}) map[string]interface{} {
//The name of the tag you will use for fields of struct
const tagTitle = "kelvin"
var data map[string]interface{} = make(map[string]interface{})
varType := reflect.TypeOf(val)
if varType.Kind() != reflect.Struct {
// Provided value is not an interface, do what you will with that here
fmt.Println("Not a struct")
return nil
}
value := reflect.ValueOf(val)
for i := 0; i < varType.NumField(); i++ {
if !value.Field(i).CanInterface() {
//Skip unexported fields
continue
}
tag, ok := varType.Field(i).Tag.Lookup(tagTitle)
var fieldName string
if ok && len(tag) > 0 {
fieldName = tag
} else {
fieldName = varType.Field(i).Name
}
if varType.Field(i).Type.Kind() != reflect.Struct {
data[fieldName] = value.Field(i).Interface()
} else {
data[fieldName] = StructToMap(value.Field(i).Interface())
}
}
return data
}
map := Structpb.AsMap()
// map is the map[string]interface{}