I'm trying to use a time.Time structure in a structure that will be encoded/decoded with JSON. The time.Time attributes should not be included if they aren't set (omitempty tag), so to be able to do so I will have to use a pointer to the time.Time object.
I have defined a type for the time.Time structure so I easily can create receiver functions format the time when the JSON is encoded and decoded etc.
See the code here: https://play.golang.org/p/e81xzA-dzz
So in my main structure (the structure that actually will be encoded) I will do something like this:
type EncodeThis struct {
Str string `json:"str,omitempty"`
Date *jWDate `json:"date,omitempty"`
}
The problem is that the pointer may be nil, when trying to decode the value, so if you look at my code at the Go playground, you can see that I'm trying to (using double pointers) to set the address of the receiver if its nil. See method "Set" and "swap".
But, this doesnt seem to work. The program doesn't fail or anything, but the "EncodeThis" struct will not contain a reference to this new address. Any idea for a fix for this?
Wrap your date object with a struct containing a pointer to time.Time object.
// JWDate: Numeric date value
type jWDate struct {
date *time.Time
}
func (jwd *jWDate) Set(t *time.Time) {
if jwd.date == nil {
jwd.date = t
}
}
If you need to have access to time.Time methods from jWDate struct you can embed it. With embedded type you still have ease access to an object's pointer:
// JWDate: Numeric date value
type jWDate struct {
*time.Time // Embedded `time.Time` type pointer, not just an attribute
}
func (jwd *jWDate) Set(t *time.Time) {
if jwd.Time == nil {
jwd.Time = t
}
}
Related
I have a map of type set, which is actually a map[string]string. However, passing it to a function which accepts a map[string]string fails, because Go does not recognize set as one.
However, I fail to convince the compiler it is one. Is there any way to resolve this, without looping and copying?
package main
import (
"fmt"
)
type name string
type field string
type set map[name]field // map[string]string after all
type plain map[string]string // also map[string]string
func main() {
var typed = set{"hi": "ho"} // map[string]string?
back := plain(typed) // cannot convert typed (type set) to type plain
back := typed.(plain) // invalid type assertion: typed.(plain) (non-interface type set on left)
echo(back)
}
func echo(in map[string]string) {
fmt.Println(in)
}
You could do this using the unsafe package.
Note: I don't think this would necessarily be a good idea, and probably the right way would be to just iterate and copy, but since it does answer the question asked...
var typed = set{"hi": "ho"} // map[string]string?
p := unsafe.Pointer(&typed)
var back plain
back = *(*plain)(p)
Playground: https://play.golang.org/p/yienSuJSnQU
Whenever I retrieve the address of an appended struct into an slice of structs that implements an interface, its pointer address seems to change.
Playground: https://play.golang.org/p/MmAS6S5IqH
package main
import (
"fmt"
)
type Apple struct {
Rotter
Color string
}
func (a *Apple) GetColor() string {
return a.Color
}
type Shop struct {
Rotters []Rotter
}
type Rotter interface {
GetColor() string
}
func main() {
red_apple := &Apple{Color: "Red"}
fmt.Println(red_apple.GetColor())
fmt.Println(&red_apple)
grocer := &Shop{}
grocer.Rotters = append(grocer.Rotters, red_apple)
for _, fruit := range grocer.Rotters {
fmt.Println(fruit.GetColor())
fmt.Println(&fruit)
}
}
As seen when printed out in the results, the addresses of the structs does change however the values stay the same.
From what I've understand online is that when a struct implements a interface, there is some additional memory data stored with the struct. (I'm assuming this is whats changing my address)
To get to my question, can I somehow change my slice or struct in order to get around this issue and hopefully not go down the reflection route. By "get around" I mean get the original address via the slice.
The code in the question prints the addresses of local variables red_apple and fruit. They are different variables and therefore have different addresses.
The pointer value added to the slice is the same as the value in the interface retrieved from the slice. Try this:
red_apple := &Apple{Color: "Red"}
fmt.Println(red_apple.GetColor())
fmt.Printf("%p\n", red_apple) // print the value in red_apple as a pointer
grocer := &Shop{}
grocer.Rotters = append(grocer.Rotters, red_apple)
for _, fruit := range grocer.Rotters {
fmt.Println(fruit.GetColor())
fmt.Printf("%p\n", fruit) // print the value in fruit as a pointer
fmt.Println(fruit == red_apple)
}
Run it on the playground.
Note that this is not a printing issue. I use the %p format here because the output for fmt.Println(red_apple) and fmt.Println(fruit) print &{<nil> Red} instead of the pointer value.
The key point is that you should print the value added to and retrieved from the slice, not the address of the local variables.
In your code, red_apple and grocer.Rotters[0] are not the same thing. One is a direct pointer to an Apple, and the other is a Rotter interface value.
A variable of an interface type is itself a pointer to a structure that is a combination of type information, and the underlying value (the real pointer in this case).
So your second printing is giving the address to the interface value, not the underlying implementation's value.
This question has some better details on how interface values are stored.
Given any function that takes a parameter of type interface{} how would I know whether or not to pass that parameter with or without & without navigating the source code of the function.
For example if I had a function with this type signature given to me:
func foo(x interface{}, y int) int
Would there be any way to figure out if x was supposed to be passed by value or by pointer?
Here is the snippet from the source:
// DecodeElement works like Unmarshal except that it takes
// a pointer to the start XML element to decode into v.
// It is useful when a client reads some raw XML tokens itself
// but also wants to defer to Unmarshal for some elements.
func (d *Decoder) DecodeElement(v interface{}, start *StartElement) error {
val := reflect.ValueOf(v)
if val.Kind() != reflect.Ptr {
return errors.New("non-pointer passed to Unmarshal")
}
return d.unmarshal(val.Elem(), start)
}
It is checking val.Kind() != reflect.Ptr Which means you have to pass the pointer i.e &v.
Its entirely depend on the person who wrote the method or function, so interface{} could be either *ptr or anything but u ve to check that inside your function using reflect.ValueOf(v).Kind() whether the value is a pointer or not and proceeds accordingly.
And little bit about empty interface:
The interface type that specifies zero methods is known as the empty interface:
interface{}
An empty interface may hold values of any type. (Every type implements at least zero methods.)
Empty interfaces are used by code that handles values of unknown type. For example, fmt.Print takes any number of arguments of type interface{}.
Another useful discussion: docs
DecodeElement() and friends have a formal v interface{} whose type is documented in the Unmarshal() function documentation:
Unmarshal parses the XML-encoded data and stores the result in the
value pointed to by v, which must be an arbitrary struct, slice, or
string.
So to literally answer your question, no, you cannot know without reading the source - if the value you want to pass is a struct proper, you need to indirect. If it is already a pointer to that struct, you do not.
For example:
type Result struct {
XMLName xml.Name `xml:"Person"`
Name string `xml:"FullName"`
Phone string
Email []Email
Groups []string `xml:"Group>Value"`
Address
}
var (
a Result
b *Result
c string
)
xmlDecoder.DecodeElement(&a, startElement)
xmlDecoder.DecodeElement(&c, startElement)
but
xmlDecoder.DecodeElement(b, startElement)
Original question:
I'm trying to do some deserialization and I'm a little confused about how to access a struct when passing in an interface.
package main
import (
"fmt"
"reflect"
)
type Robot struct {
Id int
}
func f(i interface{}) {
v := reflect.ValueOf(i).Elem().FieldByName("Id")
fmt.Println("fields: ", reflect.ValueOf(i).Elem().NumField())
ptr := v.Addr().Interface().(*int)
*ptr = 100
}
func main() {
robot := Robot{}
var iface interface{} = robot // if I omit this line and pass in robot this works
f(&iface)
fmt.Println(robot.Id) //I want to get here 100
}
http://play.golang.org/p/y6UN3KZxRB
The play example works if you just pass in the struct directly, however as it's possible for anything to be passed in that implements a specific interface (in my example case I'm just using the empty interface). However I can't figure out how to then treat it as a struct underneath.
Updated:
package main
import (
"fmt"
"reflect"
)
type MessageOne struct {
Header string `FixedWidth:0,4`
FieldOne string `FixedWidth:"4,4"`
FieldTwo string `FixedWidth:"8,4"`
}
type MessageTwo struct {
FieldX string `FixedWidth:"X,Y"`
FieldY string `FixedWidth:"X,Y"`
}
var (
messageMap = map[string]interface{}{
"msg1": MessageOne{FieldOne: "testValueUnchanged"},
"msg2": MessageTwo{},
}
)
func deserialize(input string, i interface{}) interface{} {
value := reflect.ValueOf(i)
fmt.Println("1st Value Type: ", value.Kind())
// unswarp ptr
value = value.Elem()
fmt.Println("Unwrapped: ", value.Kind())
value = value.Elem()
fmt.Println("Unwrapped: ", value.Kind())
// Create a copy that I can set?
copyValue := reflect.New(value.Type()).Elem()
fmt.Println("Orig Struct is settable", value.CanSet())
fmt.Println("Orig StructField0 is settable", value.Field(0).CanSet())
fmt.Println("Copy is: ", copyValue.Kind())
fmt.Println("Copy Struct is settable", copyValue.CanSet())
fmt.Println("Copy StructField0 is settable", copyValue.Field(0).CanSet())
fmt.Println("Orig struct type is: ", value.Type())
fmt.Println("Copy struct type is: ", copyValue.Type())
copyValue.Field(1).SetString("testValueChanged")
return copyValue.Interface()
}
func GetMessageFromInput(input string) interface{} {
selector := input[0:4]
fmt.Println(selector)
field := messageMap[selector]
return deserialize(input, &field)
}
func main() {
val := messageMap["msg1"]
serializedData := "msg1.012345678"
deserializedVal := GetMessageFromInput(serializedData)
//msg1 := deserializedVal.(MessageOne)
fmt.Printf("Orig: %+v \nReceived: %+v", val, deserializedVal)
}
http://play.golang.org/p/Cj9oPPGSLM
I got the idea of copying my struct and thereby getting an addressable instance from here: https://gist.github.com/hvoecking/10772475
So I guess my question is now, is there a mechanism to access an addressable / settable struct without having to resort to a copy?
The underlying problem is taking strings (byte arrays really) and having a struct have the necessary info to effectively deserialize it without having to write a couple dozen deserialization functions which would suck to maintain. So the tags in those sample structs aren't addressed in the sample question, but accessing the structs tag fields would provide the offsets from which to populate the struct from the input bytes. Obviously I haven't gotten that far. Part of my frustration here is that it seems I've worked very hard to not get very far and I don't feel like i've learned much in the process.
Some additional play edits that got me my tags back:
http://play.golang.org/p/2DbbWLDKPI
You don't want to pass a pointer to the interface, you want to pass in a pointer to your struct itself.
robot := &Robot{}
f(robot)
http://play.golang.org/p/owv-Y4dnkl
The moment you assigned robot to iface, you created a copy of the robot value. There's is no way to ever get a reference back to robot from iface.
When you pass in f(&iface), the call to reflect.ValueOf(i).Elem() is just returning the inner iface value, not a Robot struct value.
In your original code, use:
var iface interface{} = &robot
f(iface)
Explanation
In the original version, we are sending in the address of the interface variable (which is a copy of the robot). This sends a pointer of type interface, and so reflect works on the copy of the robot.
var iface interface{} = robot
f(&iface)
What we need to do, is assign a pointer of type robot to the interface variable. Thus, when we send the interface we are sending the pointer of type robot, so reflect works with the actual robot object and not a copy.
var iface interface{} = &robot
f(iface)
You could use Type Assertion.
value, ok := i(Robot)
if ok {
fmt.Println(value.Id)
}
From this stackoverflow post.
I want to extend the regexp from the Go standard library to be able to define my own methods. I use the following struct:
type RichRegexp struct {
*regexp.Regexp
}
As you can see, this struct contains nothing but the wrapped regexp.Regexp. So I wonder whether I could replace this with a simple type declaration like this:
type RichRegexp regexp.Regexp
But how should I write the following func then?
func Compile(expression string) (*RichRegexp, error) {
regex, err := regexp.Compile(expression)
if err != nil {
return nil, err
}
return &RichRegexp{regex}, nil // How to do this?
}
I tried to convert regexp.Regexp to my RichRegexp but it didn't compile. What is the general pattern to return a custom type which wraps a underlying type?
You can use a conversion, but in this case it is necessary, that your type definition is not a pointer:
type MyRegexp *regexp.Regexp // Doesn't work
This is backed by the spec:
The receiver type must be of the form T or *T where T is a type name.
The type denoted by T is called the receiver base type; it must not be
a pointer or interface type and it must be declared in the same
package as the method. The method is said to be bound to the base type
and the method name is visible only within selectors for that type.
However, you can do this:
type MyRegexp regexp.Regexp
As you're handling values now, you can do the following:
x := regexp.MustCompile(".*")
y := MyRegexp(*x)
And you have your own regexp type.
Full code at play: http://play.golang.org/p/OWNdA2FinN
As a general pattern, I would would say:
If it's unlikely to change and you don't need to store arbitrary values, use
a type conversion.
If you need to store values along with your embedded type, use a struct.
If your code is likely to change and needs to support large varieties of things,
define an interface and don't use embedding / type conversion.
package main
import (
"regexp"
)
type RichRegexp regexp.Regexp
func Compile(expression string) (*RichRegexp, error) {
regex, err := regexp.Compile(expression)
if err != nil {
return nil, err
}
return (*RichRegexp)(regex), nil
}
func main() {
Compile("foo")
}
Also here: http://play.golang.org/p/cgpi8z2CfF