So I think the current state of unsafe conversions of string <-> []byte is 
roughly

1. Use the reflect Slice/StringHeader struct. These structs give you clear 
fields to set and read from. If the runtime representation of a string or 
[]byte ever changes then these structs should change to reflect this (they 
have a non-backwards compatibility carve out in the comments). But this 
also means that you run into all these exotic problems because these two 
structs have a `uintpr` an `unsafe.Pointer` so for a short time the GC 
won't realise you are reading/writing a pointer. This makes correct use of 
these structs very difficult.
2. You can just cast between these two types going through `unsafe.Pointer` 
on the way. This works, because these two types have almost identical 
layouts. We don't use any uintptr at all and so the GC probably won't get 
confused. But, if the representations of string or []byte ever change then 
you code breaks silently, and could have very weird/hard to track down 
problems.

So I don't think `neither is safer than the other` is quite the right 
description in this context. They both have problems, so they are both 
not-perfect. But their problems are quite distinct. At the least if we 
choose one over the other we can describe clearly which set of problems we 
want to have.

My hope was that someone had thought through these problems and could 
indicate the right way to do it.

On a related note. I was trying to track down where the Slice/StringHeader 
was first introduced. It was a long time ago 

<Rob Pike> (10 years ago) 29e6eb21ec  (HEAD)

make a description of the slice header public

R=rsc
DELTA=18  (3 added, 0 deleted, 15 changed)
OCL=31086
CL=31094

Although I couldn't open that CL in gerrit (I assume user-error). From 
reading the commit I think the intention was for these header structs to be 
used for this or similar things. But the data was represented as a uintptr 
and a comment explicitly states that these structs are of no use without 
`unsafe.Pointer`. I have seen roughly three other CL which try to change 
the data field to `unsafe.Pointer` but are rejected because they change the 
reflect packages API.

There is also this issue

https://github.com/golang/go/issues/19367

Which proposes that Slice/StringHeader be moved/duplicated in unsafe and 
use `unsafe.Pointer`. As far as I can tell once we have this then all the 
subtle problems disappear and lovingly crafted examples like

https://github.com/m3db/m3x/blob/master/unsafe/string.go#L62

just become the right way to do it.

Until then maybe we should just rely on the structural similarities between 
the two types and cast between them. This seems especially appealing as Jan 
pointed out above that at least one of the hypothetical problems isn't 
hypothetical at all.


On Monday, 23 September 2019 12:43:34 UTC+2, kortschak wrote:
>
> Any particular reason for that? Neither is safer than the other and 
> it's not clear to me that you can actually achieve the goal of having a 
> compile-time check for the correctness of this type of conversion. 
>
> On Mon, 2019-09-23 at 02:36 -0700, fra...@adeven.com <javascript:> wrote: 
> > But this relies on a string's representation being the same as, but a 
> > bit smaller thabn, a []byte. I would prefer to use 
> > the Slice/StringHeader. 
>
>

-- 
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/422ca2bd-d6c8-4ebe-9578-8dd3cd8317e9%40googlegroups.com.

Reply via email to