That would work Kortschak.

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.

It's worth noting that _most_ of the problems I described in my initial 
post are hypothetical at this stage. The issue with strings being garbage 
collected mid-conversion are (I think) certain not to happen in Go 1.12 and 
the problems with storing a uinptr in a variable are mostly related to 
moving garbage collectors (so long as the location your uintpr points to 
doesn't get garbage collected). But both of these facts have a reasonable 
likely hood of changing in the future.

The thing I would like the most is an pair of unsafe string <-> []byte 
conversion implementations which satisfy the rules of unsafe as they are 
written now which will _not_ compile if the representation of []byte/string 
changes in the future.

This was what I thought I would get using the reflect.Slice/StringHeader 
structs and some unsafe. It's surprising that this doesn't work in a 
straight-forward way.

On Saturday, September 21, 2019 at 8:11:08 AM UTC+2, kortschak wrote:
>
> func bytesToString(b []byte) string { 
>         return *(*string)(unsafe.Pointer(&b)) 
> } 
>
> https://play.golang.org/p/azJPbl946zj 
>
> On Fri, 2019-09-20 at 13:30 -0700, Francis wrote: 
> > Thanks Ian, that's a very interesting solution. 
> > 
> > Is there a solution for going in the other direction? Although I 
> > excluded 
> > it from the initial post, it was only to reduce the size of the 
> > discussion. 
> > I would also like to implement 
> > 
> > func BytesToString(b []byte) string { 
> > 
> > I don't clearly see how to avoid using the StringHeader in this case. 
> > 
> > F 
> > 
> > On Wednesday, 18 September 2019 22:46:44 UTC+2, Ian Lance Taylor 
> > wrote: 
> > > 
> > > On Wed, Sep 18, 2019 at 2:42 AM Francis <francis...@gmail.com 
> > > <javascript:>> wrote: 
> > > > 
> > > > I am looking at the correct way to convert from a byte slice to a 
> > > > string 
> > > 
> > > and back with no allocations. All very unsafe. 
> > > > 
> > > > I think these two cases are fairly symmetrical. So to simplify 
> > > > the 
> > > 
> > > discussion below I will only talk about converting from a string to 
> > > []byte. 
> > > > 
> > > > func StringToBytes(s string) (b []byte) 
> > > 
> > > No reason to use SliceHeader, and avoiding SliceHeader avoids the 
> > > problems you discuss. 
> > > 
> > > func StringToBytes(s string) []byte { 
> > >     const max = 0x7fff0000 
> > >     if len(s) > max { 
> > >         panic("string too long") 
> > >     } 
> > >     return 
> > > (*[max]byte)(unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer( 
> > > &s)).Data))[:len(s):len(s)] 
> > > 
> > > } 
> > > 
> > > Of course, as you say, you must not mutate the returned []byte. 
> > > 
> > > Ian 
> > > 
> > 
> > 
>
>

-- 
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/8bff6f8e-487a-4c69-a55e-513855d846da%40googlegroups.com.

Reply via email to