I'm unable to get value from Pointer receiver. It keeps returning memory address.
I'm trying to access values from the pointer receivers from other file in this below format
package types
import (
// "Some product related imports"
"golang.org/x/oauth2"
"time"
)
type TestContext struct {
userId string
}
func (cont *TestContext) GetUserId() string {
return cont.userId
}
I'm trying to solve it through multiple ways but either getting memory address, nil values or error.
Always write clean code:
Name userID not userId.
Name UserID() not GetUserId().
use ctx2 := &myType.myType{} instead of ctx2 := *myType.myType{}.
try this code:
package main
import (
"fmt"
)
type myType struct {
userID string
}
func (cont *myType) UserID() string {
return cont.userID
}
func main() {
ctx1 := myType{"1"}
fmt.Println(ctx1.UserID()) // 1
ctx := myType{"2"}
var101 := ctx.UserID()
fmt.Println(ctx1.UserID(), var101) // 1 2
ctx2 := &myType{}
fmt.Println(ctx2) // &{}
var ctx3 *myType
fmt.Println(ctx3) // <nil>
}
Output:
1
1 2
&{}
<nil>
For Technique 1. I'm not sure what logging.Debug() does but I think you are trying to pass a string to it. In this case use ctx2.GetUserId() not ctx2.GetUserId. I know it's sounds silly but to call a function that takes no parameters you still need the brackets.
The major problem is that you are using the myType package but you think you are using the types package. Otherwise I think technique 2 would be OK.
And as Volker implied about tehcnique 3 you need to use & not * to take the address of an object.
Related
Here is the simplified code of a cache. Suppose Container placed in a package, so it don't know about Member.
While I wanna store instances of Member in Container, So I store an empty instance of Member in Container as outerType.
In the Container->GetMysql, I fill a new variable by test values (but, in real world, It fill by data of database, dynamically).
then in the function Put, I store data in items as Cache for next uses. In the Get I get the data stored in the items.
Before this every thing is fine. My problem is where i want to convert result of Get to type of Member m = res.(Member) . How Can I convert it to an instance of Member
I found many question about this subject, but none of them solved my problem
For more detail: I want the Get return data with its pointer of where it stored in items. So if I get some variable of same member, an change in one are shown in others
package main
import (
"fmt"
"reflect"
)
type Member struct {
Id int
Name string
Credit int
Age int
}
type Container struct {
outerType interface{}
items map[string]*interface{}
}
func (cls *Container)GetMysql(s string, a int64) interface{}{
obj := reflect.New(reflect.TypeOf(cls.outerType))
elem := obj.Elem()
//elem := reflect.ValueOf(o).Elem()
if elem.Kind() == reflect.Struct {
f := elem.FieldByName("Name")
f.SetString(s)
f = elem.FieldByName("Credit")
f.SetInt(a)
}
return obj.Interface()
}
func (cls *Container)Get(value string) *interface{}{
return cls.items[value]
}
func (cls *Container)Put(value string, a int64) {
res := cls.GetMysql(value, a)
cls.items[value] = &res
}
func main() {
c := Container{outerType:Member{}}
c.items = make(map[string]*interface{})
c.Put("Jack", 500)
res := c.Get("Jack")
fmt.Println(*res)
m := &Member{}
m = res.(Member) // Here is the problem. How to convert ?
fmt.Println(m)
}
You should hardly ever use pointer to interface. My advice is to never use it, when you'll need it, you'll know.
Instead if you need a pointer to something (so you can have the same pointer at multiple places, and so modifying the pointed value somewhere, it will have effect on the others), "wrap the pointer" in the interface value.
So first modify the items field so that it stores interface{} values instead of pointers:
items map[string]interface{}
This means no restriction: you can pass and store pointers, that's not a problem.
Next modify Get() to return interface{}:
func (cls *Container) Get(value string) interface{}{
return cls.items[value]
}
And also in Put(), don't take the address of an interface{}:
func (cls *Container) Put(value string, a int64) {
res := cls.GetMysql(value, a)
cls.items[value] = res
}
And you have to type-assert *Member from the values returned by Get().
And now testing it:
c := Container{outerType: Member{}}
c.items = make(map[string]interface{})
c.Put("Jack", 500)
res := c.Get("Jack")
fmt.Println(res)
m := res.(*Member) // Here is the problem. How to convert ?
fmt.Println(m)
Output (try it on the Go Playground):
&{0 Jack 500 0}
&{0 Jack 500 0}
Now if you would modify a field of m:
m.Credit = 11
And then get the value form the cache:
fmt.Println(c.Get("Jack"))
We'll see the modified value, even though we did not call Put() (try it on the Go Playground):
&{0 Jack 11 0}
I have a struct with a field of the form field []interface{}. If I print the field, I get back a pointer reference. If I try to dereference the field, I get an error "invalid indirect".
The code is below:
type MyType struct {
field []interface{}
}
myType := //create a MyType. Field is just an array of numbers
println(myType.field) // prints a pointer reference, ex: [1/1]0xc420269aa0
println(*(myType.field)) // doesn't compile
How do I print the values in myType.field?
The answer is to loop through the array, or even better, use fmt.Println.
func dump(items []interface{}) {
for i := 0; i < len(items); i++ {
fmt.Println(items[i])
}
}
// OR
fmt.Println(items)
another way you could use
https://play.golang.org/p/4lLQ4Gb2S0m
package main
import (
"encoding/json"
"fmt"
)
func main() {
fmt.Println(dump(new(bool)))
fmt.Println(dump([]interface{}{new(bool), new(string)}))
}
func dump(x interface{}) string {
json, err := json.MarshalIndent(x, "", " ")
if err != nil {
panic(err)
}
return string(json)
}
// Outputs:
// false
// [
// false,
// ""
// ]
Array interfaces can be printed as follows
questionSet := []interface{}{}
// ... code to fillup the question set
fmt.Printf("%t", questionSet)
and here is the result
[%!t(*domain.Question=&{First Economics question 3
[{Economics option 1 for student false}
{Economics option 2 for student false}
{Economics option 3 for student true}
{Economics option 4 for student false}]
[{Economics first topic} {Economics second topic}]})
%!t(*domain.Question=&{second Question 4
[{Qs2 Option 1 for student false}
{Qs2 Option 2 for student false}
{Qs2 Option 3 for student false}
{Qs2 Option 4 for student false}]
[{third topic} {fourth topic}]})]
The output here is not very pretty but at least you can see the result and extract your relevant information for further process.
In the above result domain.Question is a struct and here is the complete struct for your reference. Hope this will help you to understand better.
type Question struct {
Questions string `json:"questions,omitempty" bson:"questions"`
Marks string `json:"marks,omitempty" bson:"marks"`
Options []QuestionOptions `json:"options,omitempty" bson:"options"`
Topics []QuestionTopic `json:"topics,omitempty" bson:"topics"`
}
type QuestionOptions struct {
Option string `json:"option" bson:"option"`
Correct bool `json:"correct" bson:"correct"`
}
type QuestionTopic struct {
Topic string `json:"topic" bson:"topic"`
}
Consider that the verb %t is designed to print boolean (see the doc overview at https://golang.org/pkg/fmt/), as such, while using it to dump the content of a value works as of today, it is not the behavior intended by go authors, and as such, this behavior might change in the future.
Peace,
TL;DR Somehow, I am appending a pointer to a list instead of the object within a for loop of objects so at the end the entire slice is composed of the same object multiple times. I just don't know how to fix that.
The Long Way
I am still having a super hard time trying to figure out pointers in go. I posted a question yesterday and got some help but now I am stuck on a slightly different issue in the same piece of code.
I am working with gocql and cqlr go packages to try and bit a small object mapper for my Cassandra queries. Essentially the problem I am having is I am appending what appears to be a pointer to an object, not a new instance of the obj to the array. How do I fix that? I have tried adding & and * in front of value but that doesn't seem to work. How do I fix these? The bind function needs an & according to their docs.
Code
type Query struct {
query string
values interface{}
attempts int
maxAttempts int
structType reflect.Type
}
func (query Query) RetryingQuery() (results []interface{}) {
var q *gocql.Query
if query.values != nil {
q = c.Session.Query(query.query, query.values)
} else {
q = c.Session.Query(query.query)
}
bindQuery := cqlr.BindQuery(q)
value := reflect.New(query.structType).Interface()
for bindQuery.Scan(value) {
fmt.Println(value)
results = append(results, value)
}
return
}
The docs ask for var value type then in bind you would pass &value. I quoted the docs below.
var t Tweet
var s []Tweet
for b.Scan(&t) {
// Application specific code goes here
append(s, t)
}
The issue is I cannot directly go var value query.structType to define its type then pass the reference of that to bindQuery.Scan().
What is printed
&{result1 x86_64 24 3.2.0-74-generic Linux}
&{result2 x86_64 24 3.19.0-25-generic Linux}
&{result3 x86_64 4 3.13.0-48-generic Linux}
&{result4 x86_64 2 3.13.0-62-generic Linux}
&{result5 x86_64 4 3.13.0-48-generic Linux}
What is in the slice
Spoiler, it is result5 repeated over and over. I understand that I am just appending the pointer to same object to the list and that every loop iteration the object is changed and that changes all the results in the slice to that new object. I just don't know how to fix it.
[{"hostname":"result5","machine":"x86_64","num_cpus":4,"release":"3.13.0-48-generic","sysname":"Linux"},{"hostname":"result5","machine":"x86_64","num_cpus":4,"release":"3.13.0-48-generic","sysname":"Linux"},{"hostname":"result5","machine":"x86_64","num_cpus":4,"release":"3.13.0-48-generic","sysname":"Linux"},{"hostname":"result5","machine":"x86_64","num_cpus":4,"release":"3.13.0-48-generic","sysname":"Linux"},{"hostname":"result5","machine":"x86_64","num_cpus":4,"release":"3.13.0-48-generic","sysname":"Linux"}]
Well I can at least tell you what you're doing. bindQuery takes a pointer. It changes the value stored at the address.
What you're essentially doing is this:
package main
import "fmt"
func main() {
var q int
myInts := make([]*int, 0, 5)
for i := 0; i < 5; i++ {
q = i
fmt.Printf("%d ", q)
myInts = append(myInts, &q)
}
fmt.Printf("\n")
for _, value := range myInts {
fmt.Printf("%d ", *value)
}
fmt.Printf("\n")
fmt.Println(myInts)
}
Which, as you can probably guess, gives you this:
0 1 2 3 4
4 4 4 4 4
[0x104382e0 0x104382e0 0x104382e0 0x104382e0 0x104382e0]
Things get a little more confusing with reflect. You can get your type as an interface, but that is it (unless you want to play with unsafe). An interface, in simple terms, contains a pointer to the original type underneath (and some other stuff). So in your function you are passing a pointer (and some other stuff). Then you're appending the pointer. It might be nice just to get concrete and type switch your interface. I assume you know what types it could be. In which case you'd have to have something along these lines:
package main
import (
"fmt"
"reflect"
)
type foo struct {
fooval string
}
type bar struct {
barval string
}
func main() {
f1 := foo{"hi"}
f2 := &foo{"hi"}
b1 := bar{"bye"}
b2 := &bar{"bye"}
doSomething(f1)
doSomething(f2)
doSomething(b1)
doSomething(b2)
}
func doSomething(i interface{}) {
n := reflect.TypeOf(i)
// get a new one
newn := reflect.New(n).Interface()
// find out what we got and handle each case
switch t := newn.(type) {
case **foo:
*t = &foo{"hi!"}
fmt.Printf("It was a **foo, here is the address %p and here is the value %v\n", *t, **t)
case **bar:
*t = &bar{"bye :("}
fmt.Printf("It was a **bar, here is the address %p and here is the value %v\n", *t, **t)
case *foo:
t = &foo{"hey!"}
fmt.Printf("It was a *foo, here is the address %p and here is the value %v\n", t, *t)
case *bar:
t = &bar{"ahh!"}
fmt.Printf("It was a *bar, here is the address %p and here is the value %v\n", t, *t)
default:
panic("AHHHH")
}
}
You could also just keep calling value = reflect.New(query.structType).Interface() inside of the loop which will give you new interfaces every time. Reassigning value after every append. Last time through the loop would make one extra though..
I have an issue using this statement
m.Post(Model, binding.Form(Wish), func(wish Wish, r render.Render, db *mgo.Database) {
This worked fine if I use the struct define inside the prog like
m.Post(Model, binding.Form(Wish1{}) , func(wish Wish1, r render.Render, db *mgo.Database) {
but I need this to be an independent package.
I get "Wish is not a type" wish is the return of the binding function.
This worked with a primary Type struct. I am passing the strut as a interface{}
I am using GO with Martini.Classic() It is really complicated for me to change Martini or Binding package. Any suggestions.
This is the all code
package chlistpkg
import (
"github.com/codegangsta/martini"
"github.com/codegangsta/martini-contrib/binding"
"github.com/codegangsta/martini-contrib/render"
"labix.org/v2/mgo"
"time"
"fmt"
"html/template"
"reflect"
"adminStruct"
)
just to show the struct that I need to pass as to routine Doall
type Wish1 struct {
Name string `form:"name"`
Description string `form:"description"`
AnyDate time.Time `form:"anydate"`
Active bool `form:"active"`
Number int `form:"number"`
NumDec float32 `form:"numDec"`
}
DB Returns a martini.Handler
func DB() martini.Handler {
session, err := mgo.Dial("mongodb://localhost")
if err != nil {
panic(err)
}
return func(c martini.Context) {
s := session.Clone()
c.Map(s.DB("advent2"))
defer s.Close()
c.Next()
}
}
GetAll returns all Wishes in the database
func GetAll(db *mgo.Database, entList interface{}) interface{} {
db.C("wishes").Find(nil).All(entList)
fmt.Println("GettAll entList =", entList)
return entList
}
func Doall(Model string, Wish interface{}, Wish2 interface{}, Wishlist interface{} ) {
m := martini.Classic()
fmt.Println ("martini.Classic =", m)
m.Use(martini.Static("images")) // serve from the "images" directory as well
m.Use(render.Renderer(render.Options{
Directory: "templates",
Layout: "layout",
}))
m.Use(DB())
m.Get(Model, func(r render.Render, db *mgo.Database) {
r.HTML(200, "lista4", GetAll(db, Wishlist))
})
binding does not take a pointer. I have to pass the struct by reference on "Wish"
the issue is the return on "wish Wish" I got an error Wish is not a type
at compilation time
m.Post(Model, binding.Form(Wish), func(wish Wish, r render.Render, db *mgo.Database) {
fmt.Println("Input wish =", wish)
db.C("wishes").Insert(wish)
r.HTML(200, "lista4", GetAll(db, Wishlist))
})
m.Run()
Thanks in advance
Luis
The reason you are getting an error is that you have called your type Wish1 (with a numerical 1) but you are referring to the Wish type (which does not exist!) in your code.
Change your struct to be:
// Note: "Wish", not "Wish1"
type Wish struct {
Name string `form:"name"`
Description string `form:"description"`
AnyDate time.Time `form:"anydate"`
Active bool `form:"active"`
Number int `form:"number"`
NumDec float32 `form:"numDec"`
}
If you want to put your type into another package (tip: don't overdo the sub-packages), then it will need to become a pkgname.Wish as names are fully qualified.
Added
After a second look, you're also messing things up here:
func Doall(Model string, Wish interface{}, Wish2 interface{}, Wishlist interface{} ) {
m := martini.Classic()
fmt.Println ("martini.Classic =", m)
m.Use(martini.Static("images")) // serve from the "images" directory as well
Your parameter list needs to provide a name for each type; you can't pass Wish interface{} as a parameter as Wish is a type, not a variable name.
You should either:
func DoAll(model string, wish interface{}, wish2 interface{}, wishList interface{}) { ... }
Or, better still, stop using interface{} like this and write:
func DoAll(model string, wishList []Wish, wishes... Wish) { ... }
However, your DoAll function does not seem to be referenced elsewhere, and is creating its own Martini instance. I highly suggest thinking about why things are "split out" like this if you're just starting out. Keep it simple - e.g.
func main() {
m := martini.Classic()
m.Use(martini.Static("images"))
m.Use(DB())
m.Use(render.Renderer(render.Options{...}))
// No need for an anonymous function, which just adds clutter
m.Get("/wishes/all", GetAllWishes)
// Same goes for here
m.Post("/wishes/new", PostWish)
m.Run()
}
PS: I've fixed the formatting of your code, as it has a lot of unnecessary spacing before/after parenthesis. Make sure to use gofmt, which is included with the Go install and can be hooked into most popular editors.
Is it possible to reflect on a field of a struct, and get a reference to its tag values?
For example:
type User struct {
name string `json:name-field`
age int
}
// ...
user := &User{"John Doe The Fourth", 20}
getStructTag(user.name)
// ...
func getStructTag(i interface{}) string{
//get tag from field
}
From what I can see, the usual way to do this is to range over typ.NumField(), and then call field.Tag.Get("tagname").
However, in my use-case, it would be much better to not have to pass the whole struct in.
You don't need to pass in the whole struct, but passing in the value of one of the fields is not sufficient.
In your example user.name field is just a string - the reflect package will have no way of correlating that back to the original struct.
Instead, you need to pass around the reflect.StructField for the given field:
field, ok := reflect.TypeOf(user).Elem().FieldByName("name")
…
tag = string(field.Tag)
Note: we use Elem above because user is a pointer to a struct.
You can play with an example here.
Modifying the above answer can give value of a specific tag
package main
import (
"fmt"
"reflect"
)
type User struct {
Name string `json:"name_field"`
Age int
}
func main() {
user := &User{"John Doe The Fourth", 20}
field, ok := reflect.TypeOf(user).Elem().FieldByName("Name")
if !ok {
panic("Field not found")
}
fmt.Println(getStructTag(field, "json")) //name_field
}
func getStructTag(f reflect.StructField, tagName string) string {
return string(f.Tag.Get(tagName))
}
https://play.golang.org/p/Sb0i7za5Uow
Clean way to list all tags from a struct (using external lib).
External lib: https://github.com/fatih/structs
Example: https://go.dev/play/p/C_yXMdbFYAq
package main
import (
"fmt"
"github.com/fatih/structs"
)
type User struct {
Name string `json:"name_field"`
Age int `json:"age_field"`
}
func main() {
user := &User{}
fields := structs.Fields(user)
for _, field := range fields {
tag := field.Tag("json")
fmt.Println(tag)
}
}
Result:
name_field
age_field