Skip to content

Instantly share code, notes, and snippets.

@ppanyukov
Last active October 17, 2019 15:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ppanyukov/901b32a687f3925ac0249719836b88cb to your computer and use it in GitHub Desktop.
Save ppanyukov/901b32a687f3925ac0249719836b88cb to your computer and use it in GitHub Desktop.
dirtyCast converts from []Foo to []Bar without copy.
package main
import (
"encoding/json"
"fmt"
"unsafe"
)
// dirtyCast converts from []Foo to []Bar without copy.
func dirtyCast(foos []Foo) []Bar {
res := *(*[]Bar)(unsafe.Pointer(&foos))
return res
}
type Foo struct {
X int `json:"X"`
Y int `json:"Y"`
}
type Bar struct {
// swap X and Y :) plus produce different JSON
Y int `json:"Y_flipped"`
X int `json:"X_flipped"`
}
func main() {
var foos []Foo = []Foo{
{10, 20},
{100, 200},
}
foosJson, _ := json.MarshalIndent(foos, " ", " ")
fmt.Printf("foos JSON\n%s\n\n", foosJson)
var bars []Bar = dirtyCast(foos)
barsJson, _ := json.MarshalIndent(bars, " ", " ")
fmt.Printf("bars JSON\n%s\n\n", barsJson)
// Output:
// foos JSON
// [
// {
// "X": 10,
// "Y": 20
// },
// {
// "X": 100,
// "Y": 200
// }
// ]
//
// bars JSON
// [
// {
// "Y_flipped": 10,
// "X_flipped": 20
// },
// {
// "Y_flipped": 100,
// "X_flipped": 200
// }
// ]
}
package main
import (
"encoding/json"
"fmt"
"reflect"
"unsafe"
)
// dirtyCast converts from []Foo to []Bar without copy.
// Note that Bar has 2x number of fields. lol :)
func trulyTerrifyingDirtyCast(foos []Foo) []Bar {
res := *(*[]Bar)(unsafe.Pointer(&foos))
// adjust capacity and len since Bar has 2x number of fields
header := (*reflect.SliceHeader)(unsafe.Pointer(&res))
header.Cap = header.Cap / 2
header.Len = header.Len / 2
return res
}
type Foo struct {
X int `json:"X"`
Y int `json:"Y"`
}
type Bar struct {
Y int `json:"Y_flipped"`
X int `json:"X_flipped"`
Y2 int `json:"Y2_flipped"`
X2 int `json:"X2_flipped"`
}
func main() {
var foos []Foo = []Foo{
{10, 20},
{100, 200},
}
foosJson, _ := json.MarshalIndent(foos, " ", " ")
fmt.Printf("foos JSON\n %s\n\n", foosJson)
var bars []Bar = trulyTerrifyingDirtyCast(foos)
barsJson, _ := json.MarshalIndent(bars, " ", " ")
fmt.Printf("bars JSON\n %s\n\n", barsJson)
// Output:
// foos JSON
// [
// {
// "X": 10,
// "Y": 20
// },
// {
// "X": 100,
// "Y": 200
// }
// ]
//
// bars JSON
// [
// {
// "Y_flipped": 10,
// "X_flipped": 20,
// "Y2_flipped": 100,
// "X2_flipped": 200
// }
// ]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment