Last active
October 17, 2019 15:25
-
-
Save ppanyukov/901b32a687f3925ac0249719836b88cb to your computer and use it in GitHub Desktop.
dirtyCast converts from []Foo to []Bar without copy.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
// } | |
// ] | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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