I googled "emulate c unions in go" to find examples of people wanting to do
the same thing. It appears that most (all?) of them are better solved using
Go interfaces. While I only spent a few minutes looking at the results of
my search I didn't see any examples where something like your trick was
necessary to deal with a FFI (foreign function interface). I've been
programming for more than four decades, and on UNIX for almost as long. I
am familiar with UNIX APIs that use C unions. If you are trying to deal
with a FFI it would help if you showed that as a concrete example. If, on
the other hand, you are simply trying to emulate a C union in Go then it
would help if you explained why you feel that is necessary, or preferable,
rather than using the idiomatic Go interface mechanism.

On Thu, Aug 24, 2023 at 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>
> .
>


-- 
Kurtis Rader
Caretaker of the exceptional canines Junior and Hank

-- 
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/CABx2%3DD_RWJFO7wvSWGdwMDJM9HsOQ25i9ejwbyexgf85MvCacg%40mail.gmail.com.

Reply via email to