Note that is not permitted by the rules of the unsafe package, and that in
particular it will break the garbage collector if any of the types stored
in the union contain pointer fields.

Ian

On Thu, Aug 24, 2023, 7:59 PM aind...@gmail.com <aindu...@gmail.com> wrote:

> I found this trick recently to replicate a C union in Go with
> unsafe.Sizeof, arrays, and some constant arithmetic. This lets you
> stack-allocate data that needs to be the max size of multiple other data
> types. So given a type A and B that you want to union, you can say
>
> const ASize = int64(unsafe.Sizeof(*new(A)))
> const BSize = int64(unsafe.Sizeof(*new(B)))
> const diff = ASize - BSize
> const max = ASize - ((diff>>(bits.UintSize-1))&1)*diff
>
> var storage [max]byte
> *(*A)(unsafe.Pointer(&storage))
> *(*B)(unsafe.Pointer(&storage))
>
> This process can be repeated for any number of types. For example, if you
> wanted to represent a tagged union defined like
>
> type A =
>     | B
>     | C int
>     | D (a: int, b: int)
>
> you could lower it to something like
>
> const size = int64(unsafe.Sizeof(*new(B)))
> const size0 = int64(unsafe.Sizeof(*new(C)))
> const diff = size - size0
> const max = size - diff*((diff>>(bits.UintSize-1))&1)
> const size1 = int64(unsafe.Sizeof(*new(D)))
> const diff0 = size1 - max
> const max0 = size1 - diff0*((diff0>>(bits.UintSize-1))&1)
>
> type A struct {
>         tag     uint8
>         storage [max0]byte
> }
> type B struct{}
> type C int
> type D struct {
>         a int
>         b int
> }
>
> Unfortunately, the resulting code is pretty inefficient compared to
> interfaces or struct embedding. It might be that the use of unsafe is
> hindering compiler optimizations, or maybe it's an alignment issue.
>
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/golang-nuts/5d150c6a-3ecb-4cb8-91b3-c048940294aen%40googlegroups.com
> <https://groups.google.com/d/msgid/golang-nuts/5d150c6a-3ecb-4cb8-91b3-c048940294aen%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAOyqgcXKkbH8atMfigwu0kjk-5mMcj_cPt8Y%3Dn%3DvoOZuzAmHWA%40mail.gmail.com.

Reply via email to