I am trying to create a method that will append data already cached with non-cached data pulled from the db. Ideally a single method performing something similar as below would be ideal. So is there a way to append two interface{} refs that are both slices?
package main
import "fmt"
type foo struct {
Name string
}
func main() {
a := []*foo{
&foo{"bar"},
&foo{"boom"},
}
b := []*foo{
&foo{"blam"},
&foo{"pow"},
}
fmt.Println(add(a, b))
}
func add(a, b interface{}) interface{} {
return append([]interface{}{a}, ([]interface{}{b})...)
}
Results https://play.golang.org/p/9cWxPg6daq
[[0x1040a128 0x1040a130] [0x1040a140 0x1040a148]]
Desired Results
[0x1040a128 0x1040a130 0x1040a140 0x1040a148]
Update: Benchmarks
https://play.golang.org/p/9a8aZckQAF
C:\Users\chris\Go\src\bitbucket.org\chrisolsen\test>go test -bench=.
PASS
BenchmarkWithReflection-4 300000 4580 ns/op
BenchmarkNoReflection-4 300000 4194 ns/op
ok bitbucket.org/chrisolsen/test 2.911s
Only with reflect:
func add(a, b interface{}) interface{} {
return reflect.AppendSlice(reflect.ValueOf(a), reflect.ValueOf(b)).Interface()
}
Playground: https://play.golang.org/p/FjS73G2_G5.
Notice though that this will panic if a and b are not compatible slices.
In general in Go there is no way to convert an array of one type to an array of another type. You have to do it the type specific way or run a for loop to convert each element. This is a result of how slices are implemented. See this answer:
Type converting slices of interfaces in go
The way to get the result you want with a type specific method looks like this:
https://play.golang.org/p/RqKWvQqE_g
Go does not yet have a "generics" mechanism which would make this possible with a generic annotation although some people have written code generators that function like generics in Java.
Related
I'm writing a Go application, and I want to create a test for it,
in that test, I query something from the db, insert it into a struct, and compare that struct values with a static struct of the same type that I had, if they match, the test succeeded, if not, I wanna show the difference. so I'm trying to use go-cmp package.
In general I'm getting this error:
panic: cannot handle unexported field at {main.fooTest}.F1.Int.neg:
"math/big".Int
consider using a custom Comparer; if you control the implementation of type, you can also consider using an Exporter, AllowUnexported, or cmpopts.IgnoreUnexported [recovered]
I'm getting this is because of the pgtype.Numeric that I have in my struct
type fooTest struct {
I1 int
I2 *int
S1 string
S2 *string
F1 pgtype.Numeric
F2 *pgtype.Numeric
Ff1 float64
Ff2 *float64
Ia1 []int
Ia2 []*int
Ia3 *[]int
Sa1 []string
Sa2 []*string
Sa3 *[]string
Fa1 pgtype.Float8Array
Fa2 *pgtype.Float8Array
Faf1 []float64
Faf2 []*float64
Faf3 *[]float64
}
so I tried to test with `AllowUnnexported` but the `cmp.Equal` line still fails with that error.
if !cmp.Equal(fooFoo, bar,cmp.AllowUnexported(fooTest{})) {
t.Errorf("failed test: %v",cmp.Diff(fooFoo, bar))
}
any ideas how to resolve this ?
Have you tried
cmp.Equal(fooFoo, bar, cmp.AllowUnexported(pgtype.Numeric.Int{}))
The documentation of AllowUnexported doesn't mention that it recursively applies this to all values in the struct.
Below is a sample code , which is returning multiple values .
func (c Calc) CreateTenantHandler(item *models.TenantInput) (*models.Response, *models.ErrorDetails) {
...
...
...
return &models.Response{ResponseStatus: 201, TenantOutput: tenantoutput,}, nil
}
In test file I have tried tried doing below things.
assert.Equal(t,[nil,nil],testObject.CreateTenantHandler(nil) );
I also checked other answers but couldn't find what I need.
You don't. It has nothing to do with testify--that's just how Go works. Set multiple variables to the return values, then assert each one individually:
x, y := testObject.CreateTenantHandler(nil)
assertEqual(t, x, expectedX)
assertEqual(t, y, expectedY)
The issue is that you want to convert several return values into a single value that is usable by assert.Equal.
You can do this by passing multiple values to a variadic function that converts all the values (no matter how many) into a single slice of interfaces. That slice is then treated as a single value and works quite well with testify assert.Equal.
The shim function mentioned elsewhere is close, but it has a fixed number of parameters. makeIS() below is less code, cleaner, simpler and works with any number of return values/parameters. Put this function in your test package.
// makeIS will convert any number of parameters to a []interface{}
func makeIS(v ...interface{}) []interface{} {
return v
}
Now the assert work like this
assert.Equal(t, makeIS(eX,eY), makeIS(iReturnTwoValues())
The testify knows how to make the comparison and reports differences in the individual parameters very well. Notice this has the added benefit of "looking like" the call you want to test with the two target values to the left of the function.
One simple way to do the thing you want is to declare a function like shim:
func shim(a, b interface{}) []interface{} {
return []interface{}{a, b}
}
and then:
assert.Equal(t, shim(5,6), shim(testObject.CreateTenantHandler(nil)));
The behavior is described thoroughly in the link below:
source: http://zacg.github.io/blog/2014/10/05/go-asserts-and-multiple-return-values/
you can add convert function to fix it
package multi_return
import (
"github.com/stretchr/testify/assert"
"testing"
)
func multiReturn() (int, float32) {
return 1, 2
}
func toSlice(a ...interface{}) []interface{} {
return a
}
func TestMultiReturn(t *testing.T) {
assert.Equal(t, []interface{}{int(1), float32(2)}, toSlice(multiReturn()))
}
Not able to figure out how to convert interface{} returned from function into an array of structs
As part of some practise i was trying to create a function which can take 2 slices of some type and concatenates both and returns the slice.
The code can be found here - https://play.golang.org/p/P9pfrf_qTS1
type mystruct struct {
name string
value string
}
func appendarr(array1 interface{}, array2 interface{}) interface{} {
p := reflect.ValueOf(array1)
q := reflect.ValueOf(array2)
r := reflect.AppendSlice(p, q)
return reflect.ValueOf(r).Interface()
}
func main() {
fmt.Println("=======")
array1 := []mystruct{
mystruct{"a1n1", "a1v1"},
mystruct{"a1n2", "a1v2"},
}
array2 := []mystruct{
mystruct{"a2n1", "a2v1"},
mystruct{"a2n2", "a2v2"},
}
arrayOp := appendarr(array1, array2)
fmt.Printf("arr: %#v\n", arrayOp) // this shows all the elements from array1 and 2
val := reflect.ValueOf(arrayOp)
fmt.Println(val) // output is <[]main.mystruct Value>
fmt.Println(val.Interface().([]mystruct)) // exception - interface {} is reflect.Value, not []main.mystruct
}
I may have slices of different types of structs. I want to concatenate them and access the elements individually.
If there is any other way of achieving the same, please do let me know.
reflect.Append() returns a value of type reflect.Value, so you don't have to (you shouldn't) pass that to reflect.ValueOf().
So simply change the return statement to:
return r.Interface()
With this it works and outputs (try it on the Go Playground):
=======
arr: []main.mystruct{main.mystruct{name:"a1n1", value:"a1v1"}, main.mystruct{name:"a1n2", value:"a1v2"}, main.mystruct{name:"a2n1", value:"a2v1"}, main.mystruct{name:"a2n2", value:"a2v2"}}
[{a1n1 a1v1} {a1n2 a1v2} {a2n1 a2v1} {a2n2 a2v2}]
[{a1n1 a1v1} {a1n2 a1v2} {a2n1 a2v1} {a2n2 a2v2}]
You also don't need to do any reflection-kungfu on the result: it's your slice wrapped in interface{}. Wrapping it in reflect.Value and calling Value.Interface() on it is just a redundant cycle. You may simply do:
arrayOp.([]mystruct)
On a side note: you shouldn't create a "generic" append() function that uses reflection under the hood, as this functionality is available as a built-in function append(). The builtin function is generic, it gets help from the compiler so it provides the generic nature at compile-time. Whatever you come up with using reflection will be slower.
ERROR: type CustomStruct is not an expression.
type CustomStruct struct {
}
func getTypeName(t interface{}) string {
rt := reflect.TypeOf(t).Elem()
return rt.Name()
}
getTypeName(CustomStruct)
How can I pass struct type to function without type instance?
This will work
getTypeName((*CustomStruct)(nil))
But I wonder if there is more simple version..
You can't. You can only pass a value, and CustomStruct is not a value but a type. Using a type identifier is a compile-time error.
Usually when a "type" is to be passed, you pass a reflect.Type value which describes the type. This is what you "create" inside your getTypeName(), but then the getTypeName() will have little left to do:
func getTypeName(t reflect.Type) string {
return t.Name()
}
// Calling it:
getTypeName(reflect.TypeOf(CustomStruct{}))
(Also don't forget that this returns an empty string for anonymous types such as []int.)
Another way is to pass a "typed" nil pointer value as you did, but again, you can just as well use a typed nil value to create the reflect.Type too, without creating a value of the type in question, like this:
t := reflect.TypeOf((*CustomStruct)(nil)).Elem()
fmt.Println(t.Name()) // Prints CustomStruct
Lets resurrect this!
The generics proposal for Go got approved, and that's coming, eventually. When this question was first asked, this probably made more sense as a question, but for anyone looking to implement a generics pattern now, I think I've got an alright API for it.
For now, you can't interact with abstract types, but you can interact with methods on the abstract type, and reflect allows you to examine function signatures. For a method, the 0th is the receiver.
type Example struct {int}
type Generic struct{reflect.Type}
func (p Example) Type() {}
func Reflect(generic interface{}) Generic {
real := reflect.TypeOf(generic)
if real.Kind() != reflect.Func || real.NumIn() < 1 {
panic("reflect.Type.In(n) panics if not a func and if n out of bounds")
}
return Generic{real.In(0)}
}
func (g Generic) Make() interface{} {
return reflect.Zero(g.Type).Interface()
}
func main() {
tOfp := Reflect(Example.Type)
fmt.Printf("Name of the type: %v\n", tOfp.Name())
fmt.Printf("Real (initial)value: %v\n", tOfp.Make())
}
Some quick notes:
The structure of "Example" doesn't matter, rather only that it has a method with a non-pointer receiver.
The definition of a type called "Generic" as a struct is to accomplish what I believed OP's actual intent to be.
The above definition of "Generic" is a struct instead of an interface so that it can have its own method set. Defining "Generic" as an interface, and using a methodset specific to each operand-type used with it would make tons of sense.
If you weren't aware, actual generics are coming in Go 1.18. My example above has no linter or compile protection, and will panic at runtime if used incorrectly. It does work, and will let you reason over abstract types while you wait for a native implementation.
Happy Coding!
From Go version 1.18 a new feature Generics has been introduced. In most of the case instead of passing types to function, we can use generics. Then we will also get compile time error instead of runtime error and it's more efficient than reflect also.
Example Code
func HttpGet[T](url, body) T {
var resp T
return T
}
resp := HttpGet[ResponseType]("dummy.example", nil)
Can anyone tell me how to create a new instance of Type from a string? Reflect?
There are examples but they are for the older (pre Go 1 versions) of the language [:(]
So, if I understand your question correctly, you are asking about how you can create an object when you just have the name of the type as string. So, for example, you might have a string "MyStruct" and you want to create an object of this type.
Unfortunately, that's not easily possible because Go is a statically typed language and the linker will eliminate dead code (or inline parts of it). So, there is no guarantee, that your final executable will even contain the code of "MyStruct".
You can however, maintain a global map[string]reflect.Type manually. For example by initializing this map in the init() function of your packages which defines such discover-able types. This will also tell the compiler that you are using the types. Afterwards, you can use this map to look up the reflect.Type of the type you want to create and use reflect.New to get a pointer to a new object of that type (stored as a reflect.Value). You can extract the object into an interface with something like this:
reflect.New(yourtype).Elem().Interface()
Elem() will de-reference the pointer and Interface() will return the reflected value as an interface{}. See The Laws of Reflection for further details.
PS: There might be a better way to structure your program which doesn't even require reflection and which let the compiler catch more errors. Have you considered using a factory method for example? An other easy solution might be to maintain a map[string]func() interface{} of functions which can be invoked to create a new object with that name.
Factory with predefined constructors can be based on something like:
package main
import (
"fmt"
)
type Creator func() interface{}
type A struct {
a int
}
type B struct {
a bool
}
func NewA() interface{} {
return new(A)
}
func NewB() interface{} {
return new(B)
}
func main() {
m := map[string]Creator{}
m["A"] = NewA
m["B"] = NewB
for k, v := range m {
fmt.Printf("%v -> %v\n", k, v())
}
}