Proposal: allow type conversions of slices when underlying type have the same memory layout

93 views
Skip to first unread message

awaw...@gmail.com

unread,
Dec 19, 2025, 9:23:30 PM (2 days ago) Dec 19
to golang-nuts
Hi fellow Gophers

I'd like to propose that we allow type casting between `[]T` and `[]U`, when the underlying types `T` and `U` are identical.

For example:

```
type Symbol byte

func Index(a, b []Symbol) int {
        return bytes.Index(a, b)
}
```

Currently, the above code does not compile with the error:

`cannot use a (variable of type []Symbol) as []byte value in argument to bytes.Index`

This proposal suggests to make this allowed since `Symbol` is exactly identical to `byte`.

I am aware this has been proposed before, but was turned down since real world needs at that time were minimal.
However, I now have a real need in my code for this feature.
Alternatively, if this kind of slice type conversion is truly disallowed, can anyone suggest a better way of writing the above function that maintains its readability and performance?

Thanks

Lidong Yan

unread,
Dec 19, 2025, 10:42:54 PM (2 days ago) Dec 19
to awaw...@gmail.com, golang-nuts
awaw...@gmail.com <awaw...@gmail.com> writes:
>
> Hi fellow Gophers

Hi
I noticed that you used `*(*[]byte)(unsafe.Pointer(&x))` to convert a []Symbol into a []byte.

I think the only downside of doing this is that the compiler will no longer help you check whether Symbol and byte are actually the same type.

As long as you add a single line like `_ = byte(Symbol(0))` in the code, you can let the compiler perform that type check for you.

- Lidong

Axel Wagner

unread,
Dec 20, 2025, 12:19:33 AM (yesterday) Dec 20
to awaw...@gmail.com, golang-nuts
This has been discussed and rejected recently:

--
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...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/5bb6ca8a-9a69-4262-a2f5-c6fb109a40a4n%40googlegroups.com.

Henry

unread,
Dec 20, 2025, 12:48:21 AM (yesterday) Dec 20
to golang-nuts
You can if you define your type as follow:

```
type Symbol = byte
```

awaw...@gmail.com

unread,
Dec 20, 2025, 12:57:51 AM (yesterday) Dec 20
to golang-nuts
Good god! Henry, you are right! `type Symbol = byte` IS the solution!
Also many thanks for Alex for pointing to issue 71183!

Issue 71183 described a decade old discussion about this problem, which explains why I have the impression this has been brought up before.
I believe at least for most cases, Henry's approach above is the correct solution, and this truly needs to be documented somewhere for further reference.
I will be commented on issue 71183 to bring wider awareness to Henry's solution.

Many thanks again to both!

Axel Wagner

unread,
Dec 20, 2025, 1:32:01 AM (yesterday) Dec 20
to awaw...@gmail.com, golang-nuts
On Sat, 20 Dec 2025 at 03:24, awaw...@gmail.com <awaw...@gmail.com> wrote:
Alternatively, if this kind of slice type conversion is truly disallowed, can anyone suggest a better way of writing the above function that maintains its readability and performance?

Oh and I would probably write the conversion instead as (possibly in a function, optionally just using len directly instead of reslicing, if you don't care about the difference):

func convert(s []Symbol) []byte {
    return unsafe.Slice((*byte)(unsafe.SliceData(s)), cap(s))[:len(s)]
}

This is still using unsafe and it is more to type/read, but it is much safer. In particular, it stops compiling if you ever change `Symbol` to no longer have underlying type `byte`. You could also use generics to get/reinforce that safety:

func convert[T ~byte](s []T) []byte {
    return *(*[]byte)(unsafe.Pointer(&s))
}

(or combine both)

Axel Wagner

unread,
Dec 20, 2025, 1:34:00 AM (yesterday) Dec 20
to awaw...@gmail.com, golang-nuts
> I believe at least for most cases, Henry's approach above is the correct solution, and this truly needs to be documented somewhere for further reference.

I thought about suggesting that, but I was assuming you where using a type definition because you wanted the types to be different (e.g. to put methods on it, or just for safety).

awaw...@gmail.com

unread,
Dec 20, 2025, 1:47:25 AM (yesterday) Dec 20
to golang-nuts
Hi Axel

Thanks for the two improvements above that enhances the safety of the `unsafe` approach.
Fortunately, the `type T = U` captures my intention sufficiently, and the main motivation for posting this discussion was to solicit suggestions to help me remove my uses of `unsafe`. (to this end this post has fulfilled its mission, and many thanks for everyone chiming in : ) )

Perhaps the Go team has indeed made the correct decision in rejected issue 71183, and it is really my problem coming from a C background.
I was perhaps too glued to C's type alias syntax `type T U`, and haven't truly internalized Go's way of doing things.
Nonetheless, I believe raising awareness to the `type T = U` trick is indeed necessary, as the decade old way of doing this conversion has always been `unsafe`.
In fact, the situation has now deteriorated to point where both Chatgpt and Gemini are now parroting the `unsafe` way of doing things.

p.s. Axel, sorry for mistyping your name in my previous post, I strive to spell it correctly in the future

Henry

unread,
Dec 20, 2025, 2:09:56 AM (yesterday) Dec 20
to golang-nuts

Happy to help. If you’re coming from C, Go’s "type Symbol = byte" is directly equivalent to C’s "typedef unsigned char Symbol". It does not create a new type; it’s purely a type alias.

By contrast, "type Symbol byte" defines a new and distinct type.


awaw...@gmail.com

unread,
Dec 20, 2025, 2:15:42 AM (yesterday) Dec 20
to golang-nuts
Henry, thanks for elucidating the difference between defining a new type and creating a type alias.
I admit I'm really just a C "user", and never a professional C programmer. I guess the same applies to my usage of Go, too.
Thanks again for this extremely educating discussion.
Reply all
Reply to author
Forward
0 new messages