How to use map as data carrier in Go? - pointers

I am unsure about correct terms, but how do I use this:
type MyType map[string]string
as "data carrier" (or object in OOP)?
This does not work:
func NewMyType() *MyType {
return make(MyType)
}
I do want to use pointer but apparently this does not work, the compiler expects reference on return.

The builtin make() function creates a non-pointer value of your MyType map type, yet the return type is a pointer. That's what the error message tells if you try to compile it:
cannot use make(MyType) (type MyType) as type *MyType in return argument
If you return a pointer to the value, it works:
type MyType map[string]string
func NewMyType() *MyType {
m := make(MyType)
return &m
}
If you would want to use a single line for it, you could use a composite literal:
func NewMyType() *MyType {
return &MyType{}
}
But maps (map values) are already implement as pointers in the background, so this is redundant and unnecessary. Just return the map-value as-is:
type MyType map[string]string
func NewMyType() MyType {
return make(MyType)
}
Or with a composite literal:
func NewMyType() MyType {
return MyType{}
}
Although "constructors" for such simple types (simple creation) are not necessary, unless you want to do other things before returning it (e.g. specify its initial capacity or fill it with initial values).

Related

How do i dereference a pointer value passed as the empty interface?

I've got a method taking a target interface{} on a type that I use for database access like:
func (c *client) Query(query someType, target interface{}) error {
return c.db.Query(query).Decode(target)
}
This is then called like
result := resultType{}
if err := c.Query(myQuery, &result); err == nil {
// do sth with result
}
Which does what I want it do as I am passing the pointer address of result
The trouble I am now running into is that I do not know how I can mock this kind of behavior (mutating the passed reference) in a test.
In case I wouldn't need to pass interface{} I could imagine it being done like this:
type mockClient struct {
targetValue resultType
}
func (m *mockClient) Query(query someType, target *resultType) error {
*target = m.targetValue
return nil
}
If I try to do the same using my actual signature, I am not able to dereference the value contained in target like this:
type mockClient struct {
targetValue interface{}
}
func (m *mockClient) Query(query someType, target interface{}) error {
target = m.targetValue // this does not mutate the passed target
return nil
}
Can I dereference a pointer value when it is passed in as the empty interface? In case it is not possible, what would be another approach of testing the side effects my method has without having to resort to concrete types as arguments?
You can use 'reflect' package to do it.
package main
import (
"fmt"
"reflect"
)
type mockClient struct {}
func (m *mockClient) Query(query string, target interface{}) error {
a := "changed"
va := reflect.ValueOf(a)
reflect.ValueOf(target).Elem().Set(va)
return nil
}
func main() {
var mc mockClient
target := "initial"
mc.Query("qwe", &target)
fmt.Println(target)
}
The simple example to reference you can find here

How to get a pointer to a variable that's masked as an interface?

I prefer not to dive into the rationale of the situation below. It has to do with unmarshaling an serialized object that can be any of a fixed set of types, but you don't know which type.
I have the following types:
type I interface {
Do()
}
type someI struct {}
func (i *someI) Do() {}
type otherI struct {}
func (i *otherI) Do() {}
So, two structs of which the pointers implement interface I.
Now I have this method that wants to return a value of type I:
func GetSomeI(marshalled []byte) (I, error) {
var obj interface{}
// The following method magically puts an instance
// of either someI or otherI into obj.
magicUnmarshall(marshalled, obj)
// The problem now is that we cannot return obj,
// because the raw structs don't implement I.
// One solution would be to do a type switch like this:
switch obj.(type) {
case someI:
i := obj.(someI)
return &i, nil
case otherI:
i := obj.(otherI)
return &i, nil
default:
return nil, errors.New("marschalled object was not of type I")
}
// But now consider the case that there are quite some
// different implementations of I.
// We would prefer to have a general way of getting
// a reference to obj.
}
To tell if a value wrapped in an interface{} implements some other interface (I), you may simply use a type assertion.
Note that you must pass the address of the variable you want results unmarshaled to.
For demonstration purposes, let's use the following magicUnmarshal() function:
func magicUnmarshal(what int, obj interface{}) {
v := reflect.ValueOf(obj).Elem()
switch what {
case 0:
v.Set(reflect.ValueOf(&someI{}))
case 1:
v.Set(reflect.ValueOf(&otherI{}))
case 2:
v.Set(reflect.ValueOf("just a string"))
case 3:
v.Set(reflect.ValueOf(someI{}))
case 4:
v.Set(reflect.ValueOf(otherI{}))
}
}
Note that case 3 and case 4 are returning non-pointers.
Your GetSomeI() implementation can be:
func GetSomeI(what int) (I, error) {
var obj interface{}
magicUnmarshal(what, &obj)
// Try the value as-is:
if i, ok := obj.(I); ok {
return i, nil
}
// No success. Try a pointer to the value:
v := reflect.Indirect(reflect.New(reflect.TypeOf(obj)))
v.Set(reflect.ValueOf(obj))
pobj := v.Addr().Interface()
if i, ok := pobj.(I); ok {
return i, nil
}
return nil, fmt.Errorf("%T does not implement I!", obj)
}
First GeSomeI() tests if the value got form magicUnmarshal() implements I, and if so, it is used as-is. If not, we construct a new using reflection, and get its address (a pointer to a value), and we test that. If that pointer implements I, we return it.
Testing it:
func main() {
for what := 0; what < 5; what++ {
i, err := GetSomeI(what)
fmt.Printf("%T %v\n", i, err)
}
}
And the output is (try it on the Go Playground):
*main.someI <nil>
*main.otherI <nil>
<nil> string does not implement I!
*main.someI <nil>
*main.otherI <nil>

How to initialize an empty pointer by reflect

This is a very straight forward question.
How do you implement Initialize() below with reflect?
Or is this possible?
func Initialize(v interface{}) {
// ... some reflection code
}
type MyType struct {
Name string
}
func main() {
var val *MyType
// val is nil before initialize
Initialize(val)
// val is now &MyType{Name: ""}
// ...
}
```
Here's how to do it:
func Initialize(v interface{}) {
rv := reflect.ValueOf(v).Elem()
rv.Set(reflect.New(rv.Type().Elem()))
}
This function must be called with a pointer to the value to set:
Initialize(&val)
playground example
The code in this answer panics if the argument type is not a pointer to a pointer. Depending on your use, you might want to check the reflect value kind before calling Elem().

How to extract the interface type name and package using reflection?

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.

How can I type select an interface on a pointer-to-pointer in Go?

I have a pair of interfaces defined like so:
type Marshaler interface {
Marshal() ([]byte, error)
}
type Unmarshaler interface {
Unmarshal([]byte) error
}
I have a simple type which implement these:
type Foo struct{}
func (f *Foo) Marshal() ([]byte, error) {
return json.Marshal(f)
}
func (f *Foo) Unmarshal(data []byte) error {
return json.Unmarshal(data, &f)
}
I am using a library which defines a different interface, and implementing it like so:
func FromDb(target interface{}) { ... }
The value being passed for target is a pointer to pointer:
fmt.Println("%T\n", target) // Prints **main.Foo
Typically this function does a type switch and then operates on the type underneath. I would like to have common code for all types that implement my Unmarshaler interface but can't figure out how to get from a pointer-to-pointer of a specific type to my interface.
You cannot define methods on a pointer to a pointer:
func (f **Foo) Unmarshal(data []byte) error {
return json.Unmarshal(data, f)
}
// compile error: invalid receiver type **Foo (*Foo is an unnamed type)
You cannot define receiver methods on pointer types:
type FooPtr *Foo
func (f *FooPtr) Unmarshal(data []byte) error {
return json.Unmarshal(data, f)
}
// compile error: invalid receiver type FooPtr (FooPtr is a pointer type)
Casting to Unmarshaler doesn't work:
x := target.(Unmarshaler)
// panic: interface conversion: **main.Foo is not main.Unmarshaler: missing method Unmarshal
Casting to *Unmarshaler doesn't work either:
x := target.(*Unmarshaler)
// panic: interface conversion: interface is **main.Foo, not *main.Unmarshaler
How can I get from this pointer-to-pointer type to my interface type without needing to switch on every possible implementor type?
It's ugly, but is is possible to have the semantic equivalent of a pointer to pointer receiver. For example:
package main
import "fmt"
type P *int
type W struct{ p P }
func (w *W) foo() {
fmt.Println(*w.p)
}
func main() {
var p P = new(int)
*p = 42
w := W{p}
w.foo()
}
Playground
Output:
42
Note that
fmt.Println(*w.p)
above is actually
fmt.Println(*(*w).p)
where the extra work is done for you by the compiler automagically.
If target is a **Foo and *Foo implements Unmarshaler, you can do:
var x Unmarshaler = *target
If target is a an interface{} containing a **Foo, this would work instead:
var x Unmarshaler = *(target.(**Foo))
It's a similar idea if you have a type switch.
Whenever I have to deal with pointer-to-pointer or pointer-to-reference, the variable life-time is generally pretty short and they quickly go back to being a single pointer (or plain reference) again.
I'd evaluate whether the pointer-to-pointer is indeed required for the use case at hand or whether you can do something like that.

Resources