3

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
chris
  • 4,332
  • 5
  • 41
  • 61

2 Answers2

3

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.

Ainar-G
  • 34,563
  • 13
  • 93
  • 119
  • 1
    While this will work, reflect is very likely to be slow. – Nick Palmer Aug 18 '16 at 17:47
  • 1
    Reflection is very likely to be slower, but before dismissing it I ran a benchmark test. Things are slower, but but the reflection time cost is just a blip in comparison to the http request latency and since the reflection is only needed when new data needs to be cached it won't be be called on all the time. – chris Aug 18 '16 at 21:22
1

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.

Community
  • 1
  • 1
Nick Palmer
  • 2,589
  • 1
  • 25
  • 34