go中string和slice no-copy轉換

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

在go裡面,string和slice的互換是需要進行記憶體拷貝的,雖然在底層,它們都只是用 pointer + len來表示的一段記憶體。

通常,我們不會在意string和slice的轉換帶來的記憶體拷貝效能問題,但是總有些地方需要關注的,剛好在看vitess代碼的時候,發現了一種很hack的做法,string和slice的轉換隻需要拷貝底層的指標,而不是記憶體拷貝。當然這樣做的風險各位就要好好擔當了:

func String(b []byte) (s string) {    pbytes := (*reflect.SliceHeader)(unsafe.Pointer(&b))    pstring := (*reflect.StringHeader)(unsafe.Pointer(&s))    pstring.Data = pbytes.Data    pstring.Len = pbytes.Len    return}func Slice(s string) (b []byte) {    pbytes := (*reflect.SliceHeader)(unsafe.Pointer(&b))    pstring := (*reflect.StringHeader)(unsafe.Pointer(&s))    pbytes.Data = pstring.Data    pbytes.Len = pstring.Len    pbytes.Cap = pstring.Len    return}

在我的測試例子中,slice轉string之後,如果slice的值有變化,string也會跟著改變,如下:

b := []byte("hello world")a := String(b)b[0] = 'a'println(a)  //output  aello world

但是string轉slice之後,就不能更改slice了,如下:

a := "hello world"b := Slice(a)b[0] = 'a'  //這裡就等著崩潰吧//但是可以這樣,因為go又重新給b分配了記憶體b = append(b, "hello world"…)

上面為什麼會崩潰我猜想可能是string是immutable的,可能對應的記憶體位址也是不允許改動的。

另外,上面這個崩潰在defer裡面是recover不回來的,真的就崩潰了,原因可能就跟c的非法記憶體訪問一樣,os不跟你玩了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.