Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Cast slice to slice of interface{}
package main
import (
"fmt"
"time"
"unsafe"
)
var (
_sliceTypeKind uintptr
eNotRelType = fmt.Errorf("Not relevant type")
)
type typeRuntime struct {
size uintptr
ptrdata unsafe.Pointer
hash uint32
tflag uint8
align uint8
fieldalign uint8
kind uint8
alg uintptr
gcdata uintptr
str int32
ptrToThis int32
}
type efaceRuntime struct {
_type *typeRuntime
data unsafe.Pointer
}
type sliceRuntime struct {
array unsafe.Pointer
len int
cap int
}
func init() {
var slice []interface{}
_sliceTypeKind = getTDPointer(slice).alg
}
func getTDPointer(data interface{}) *typeRuntime {
return (*efaceRuntime)(unsafe.Pointer(&data))._type
}
func ConvertSlice(src interface{}, elem interface{}) (dst []interface{}, err error) {
if getTDPointer(src).alg != _sliceTypeKind {
return dst, eNotRelType
}
sr := (*sliceRuntime)((*efaceRuntime)(unsafe.Pointer(&src)).data)
td := getTDPointer(elem)
dst = make([]interface{}, sr.len, sr.cap)
for i := uintptr(0); i < uintptr(sr.len); i++ {
(*efaceRuntime)(unsafe.Pointer(&dst[i]))._type = td
(*efaceRuntime)(unsafe.Pointer(&dst[i])).data = unsafe.Pointer(uintptr(sr.array) + (i * td.size))
}
return dst, nil
}
func print(a []interface{}) {
//for _, el := range a {
//fmt.Println(el)
//}
}
func main() {
ln := 100000
var a = make([]int, ln)
for i := 0; i < ln; i++ {
a[i] = i
}
start := time.Now().UnixNano()
b, err := ConvertSlice(a, a[0])
fmt.Println(time.Now().UnixNano() - start)
if err != nil {
fmt.Println(err)
} else {
print(b)
}
start = time.Now().UnixNano()
c := make([]interface{}, len(b))
for i := 0; i < len(b); i++ {
c[i] = a[i]
}
fmt.Println(time.Now().UnixNano() - start)
print(b)
}
t0pep0@leviafan /tmp $ go run test.go
1670325
18322023
t0pep0@leviafan /tmp $ go run test.go
1682478
9829742
t0pep0@leviafan /tmp $ go run test.go
1603277
10894470
t0pep0@leviafan /tmp $ go run test.go
1620877
9735874
t0pep0@leviafan /tmp $ go run test.go
1597828
13158029
t0pep0@leviafan /tmp $ go run test.go
1597410
12530573
t0pep0@leviafan /tmp $ go run test.go
1585537
11012644
t0pep0@leviafan /tmp $ go run test.go
1609633
10350968
t0pep0@leviafan /tmp $ go run test.go
1629608
9702001
t0pep0@leviafan /tmp $ go run test.go
1619480
12260778
t0pep0@leviafan /tmp $ go run test.go
1641479
12739471
t0pep0@leviafan /tmp $ go run test.go
1582673
8988643
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment