婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > golang 的string與[]byte轉換方式

golang 的string與[]byte轉換方式

熱門標簽:電話機器人軟件免費 涿州代理外呼系統(tǒng) 阿克蘇地圖標注 評價高的400電話辦理 百度地圖標注后傳給手機 excel地圖標注分布數據 外呼系統(tǒng)用什么卡 壽光微信地圖標注 外呼系統(tǒng)顯本地手機號

相對于C語言,golang是類型安全的語言。但是安全的代價就是性能的妥協(xié)。

下面我們看看Golang不想讓我們看到的“秘密”——string的底層數據。

通過reflect包,我們可以知道,在Golang底層,string和slice其實都是struct:

type SliceHeader struct {
    Data uintptr
    Len  int
    Cap  int
}
type StringHeader struct {
    Data uintptr
    Len  int
}

其中Data是一個指針,指向實際的數據地址,Len表示數據長度。

但是,在string和[]byte轉換過程中,Golang究竟悄悄幫我們做了什么,來達到安全的目的?

在Golang語言規(guī)范里面,string數據是禁止修改的,試圖通過s[0], b[0]取得string和slice數據指針地址也是不能通過編譯的。

下面,我們就通過Golang的“黑科技”來一窺Golang背后的“秘密”

//return GoString's buffer slice(enable modify string)
func StringBytes(s string) Bytes {
    return *(*Bytes)(unsafe.Pointer(s))
}
// convert b to string without copy
func BytesString(b []byte) String {
    return *(*String)(unsafe.Pointer(b))
}
// returns s[0], which is not allowed in go
func StringPointer(s string) unsafe.Pointer {
    p := (*reflect.StringHeader)(unsafe.Pointer(s))
    return unsafe.Pointer(p.Data)
}
// returns b[0], which is not allowed in go
func BytesPointer(b []byte) unsafe.Pointer {
    p := (*reflect.SliceHeader)(unsafe.Pointer(b))
    return unsafe.Pointer(p.Data)
}

以上4個函數的神奇之處在于,通過unsafe.Pointer和reflect.XXXHeader取到了數據首地址,并實現(xiàn)了string和[]byte的直接轉換(這些操作在語言層面是禁止的)。

下面我們就通過這幾個“黑科技”來測試一下語言底層的秘密:

func TestPointer(t *testing.T) {
    s := []string{
        "",
        "",
        "hello",
        "hello",
        fmt.Sprintf(""),
        fmt.Sprintf(""),
        fmt.Sprintf("hello"),
        fmt.Sprintf("hello"),
    }
    fmt.Println("String to bytes:")
    for i, v := range s {
        b := unsafe.StringBytes(v)
        b2 := []byte(v)
        if b.Writeable() {
            b[0] = 'x'
        }
        fmt.Printf("%d\ts=%5s\tptr(v)=%-12v\tptr(StringBytes(v)=%-12v\tptr([]byte(v)=%-12v\n",
            i, v, unsafe.StringPointer(v), b.Pointer(), unsafe.BytesPointer(b2))
    }
    b := [][]byte{
        []byte{},
        []byte{'h', 'e', 'l', 'l', 'o'},
    }
    fmt.Println("Bytes to string:")
    for i, v := range b {
        s1 := unsafe.BytesString(v)
        s2 := string(v)
        fmt.Printf("%d\ts=%5s\tptr(v)=%-12v\tptr(StringBytes(v)=%-12v\tptr(string(v)=%-12v\n",
            i, s1, unsafe.BytesPointer(v), s1.Pointer(), unsafe.StringPointer(s2))
    }
}
const N = 3000000
func Benchmark_Normal(b *testing.B) {
    for i := 1; i  N; i++ {
        s := fmt.Sprintf("12345678901234567890123456789012345678901234567890")
        bb := []byte(s)
        bb[0] = 'x'
        s = string(bb)
        s = s
    }
}
func Benchmark_Direct(b *testing.B) {
    for i := 1; i  N; i++ {
        s := fmt.Sprintf("12345678901234567890123456789012345678901234567890")
        bb := unsafe.StringBytes(s)
        bb[0] = 'x'
        s = s
    }
}
//test result
//String to bytes:
//0 s=      ptr(v)=0x51bd70     ptr(StringBytes(v)=0x51bd70     ptr([]byte(v)=0xc042021c58
//1 s=      ptr(v)=0x51bd70     ptr(StringBytes(v)=0x51bd70     ptr([]byte(v)=0xc042021c58
//2 s=hello ptr(v)=0x51c2fa     ptr(StringBytes(v)=0x51c2fa     ptr([]byte(v)=0xc042021c58
//3 s=hello ptr(v)=0x51c2fa     ptr(StringBytes(v)=0x51c2fa     ptr([]byte(v)=0xc042021c58
//4 s=      ptr(v)=nil>        ptr(StringBytes(v)=nil>        ptr([]byte(v)=0xc042021c58
//5 s=      ptr(v)=nil>        ptr(StringBytes(v)=nil>        ptr([]byte(v)=0xc042021c58
//6 s=xello ptr(v)=0xc0420444b5 ptr(StringBytes(v)=0xc0420444b5 ptr([]byte(v)=0xc042021c58
//7 s=xello ptr(v)=0xc0420444ba ptr(StringBytes(v)=0xc0420444ba ptr([]byte(v)=0xc042021c58
//Bytes to string:
//0 s=      ptr(v)=0x5c38b8     ptr(StringBytes(v)=0x5c38b8     ptr(string(v)=nil>
//1 s=hello ptr(v)=0xc0420445e0 ptr(StringBytes(v)=0xc0420445e0 ptr(string(v)=0xc042021c38
//Benchmark_Normal-4    1000000000           0.87 ns/op
//Benchmark_Direct-4    2000000000           0.24 ns/op

結論如下:

1、string常量會在編譯期分配到只讀段,對應數據地址不可寫入,并且相同的string常量不會重復存儲。

2、fmt.Sprintf生成的字符串分配在堆上,對應數據地址可修改。

3、常量空字符串有數據地址,動態(tài)生成的字符串沒有設置數據地址

4、Golang string和[]byte轉換,會將數據復制到堆上,返回數據指向復制的數據

5、動態(tài)生成的字符串,即使內容一樣,數據也是在不同的空間

6、只有動態(tài)生成的string,數據可以被黑科技修改

7、string和[]byte通過復制轉換,性能損失接近4倍

補充:Golang 使用unsafe.Pointer優(yōu)化byte[]與String轉換性能

我們知道一般來說對于一個String

如果想要轉換為byte[]都是通過類型轉換語法來實現(xiàn)的:

Res := string(bytes)

這種方式是Go所推薦的,優(yōu)點就是安全,盡管這種操作會發(fā)生內存拷貝,導致性能上會有所損耗,這在處理一般業(yè)務時這種損耗是可以忽略的。

但如果是拷貝頻繁的情況下,想要進行性能優(yōu)化時,就需要引入unsafe.Pointer了:

func main()  {
 var s = []byte("我永遠喜歡藤原千花.jpg")
 Res := *(*string)(unsafe.Pointer(s))
 fmt.Println(Res)
}

通過unsafe.Pointer偽造String的過程沒有發(fā)生內存拷貝,所以效率上會比發(fā)生內存拷貝的類型轉換快,但代價就是把底層數據暴露出來,這種做法是不安全的。

至于為什么Slice能通過這種方式和String轉換

我們可以看下它們的底層結構SliceHeader和StringHeader :

type SliceHeader struct {
 Data uintptr
 Len  int
 Cap  int
  } 
type StringHeader struct {
 Data uintptr
 Len  int
  }

兩種類型只差了一個字段Cap(容量),前面剩余的字段都是內存對齊的,所以可以直接轉換

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。

您可能感興趣的文章:
  • Go中string與[]byte高效互轉的方法實例

標簽:欽州 重慶 汕頭 蘭州 梅河口 雞西 銅川 吐魯番

巨人網絡通訊聲明:本文標題《golang 的string與[]byte轉換方式》,本文關鍵詞  golang,的,string,與,byte,轉換,;如發(fā)現(xiàn)本文內容存在版權問題,煩請?zhí)峁┫嚓P信息告之我們,我們將及時溝通與處理。本站內容系統(tǒng)采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《golang 的string與[]byte轉換方式》相關的同類信息!
  • 本頁收集關于golang 的string與[]byte轉換方式的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    国产精品美女久久久久aⅴ国产馆| 日韩美女视频在线| 99在线视频精品| www久久精品| 久久国产夜色精品鲁鲁99| 91免费观看视频| 亚洲免费av在线| 欧美日韩免费一区二区三区 | 在线观看不卡一区| 中文字幕精品综合| 久久机这里只有精品| 欧美大片拔萝卜| 日韩精品电影一区亚洲| 欧美视频一二三区| 免费看欧美美女黄的网站| 在线不卡免费欧美| 国产一二三精品| 国产精品久99| 欧美午夜影院一区| 久久99精品国产麻豆婷婷洗澡| 欧美精品一区二区三| 国产成人综合精品三级| √…a在线天堂一区| 欧美日韩精品一区视频| 激情五月婷婷综合| 国产精品久久久久一区| 欧美亚洲日本一区| 久久99国产乱子伦精品免费| 国产蜜臀97一区二区三区| av一区二区久久| 午夜欧美大尺度福利影院在线看 | 久久综合狠狠综合久久综合88| 狠狠色丁香婷综合久久| 欧美国产日韩一二三区| 欧美性一级生活| 国产精品一区二区在线看| 亚洲三级理论片| 91精品国产高清一区二区三区蜜臀| 国产麻豆欧美日韩一区| 亚洲欧美国产三级| 精品国产一区久久| 91偷拍与自偷拍精品| 琪琪一区二区三区| 亚洲日本va在线观看| 91精品国产一区二区| 91网站视频在线观看| 蜜臀av一区二区在线免费观看 | 亚洲欧美视频在线观看视频| 欧美日韩国产综合草草| 麻豆精品视频在线观看| 亚洲精品五月天| 日韩一区二区三区电影| 99久久久久久| 国产精品996| 五月婷婷激情综合网| 精品国产亚洲一区二区三区在线观看| 高清久久久久久| 另类小说图片综合网| 亚洲电影视频在线| 亚洲精品日韩一| 国产精品伦一区| 精品国产乱码91久久久久久网站| 91国偷自产一区二区开放时间| 国产精品影视在线观看| 视频在线观看一区二区三区| 亚洲精品免费在线观看| 自拍偷拍亚洲欧美日韩| 国产精品天美传媒沈樵| 中文字幕av一区二区三区免费看| 久久久久久免费| 日韩精品一区二区三区在线播放| 制服视频三区第一页精品| 欧美日韩精品一区二区三区蜜桃| 日本韩国欧美在线| 91丨国产丨九色丨pron| av亚洲精华国产精华精华| 高清日韩电视剧大全免费| 丁香五精品蜜臀久久久久99网站| 国产91丝袜在线观看| 粉嫩一区二区三区性色av| 国产成人自拍网| 99天天综合性| 色94色欧美sute亚洲线路一ni| 91影院在线观看| 欧美视频三区在线播放| 日韩欧美在线1卡| 久久麻豆一区二区| 国产精品乱码一区二三区小蝌蚪| 中文字幕在线播放不卡一区| 亚洲自拍偷拍综合| 美国精品在线观看| 波多野结衣一区二区三区| 色8久久人人97超碰香蕉987| 欧美日韩一区精品| 精品国产髙清在线看国产毛片| 久久久久亚洲蜜桃| 亚洲女与黑人做爰| 日韩精品一级中文字幕精品视频免费观看 | 91亚洲精华国产精华精华液| 高清国产一区二区| 色噜噜狠狠色综合中国| 色哟哟精品一区| 正在播放亚洲一区| 国产精品狼人久久影院观看方式| 亚洲精品日日夜夜| 日本不卡一二三| 成人黄页在线观看| 欧美精品少妇一区二区三区| 欧美tickle裸体挠脚心vk| 国产精品三级电影| 无吗不卡中文字幕| 成人午夜在线播放| 日韩一本二本av| 麻豆一区二区三区| 色老综合老女人久久久| 欧美电视剧在线看免费| 中文字幕在线不卡| 欧美日韩久久久一区| 国产农村妇女毛片精品久久麻豆 | 一区二区在线观看视频在线观看| 日本成人在线电影网| 99精品久久久久久| 欧美不卡视频一区| 亚洲成人精品在线观看| av成人免费在线观看| 久久亚洲欧美国产精品乐播| 天天免费综合色| 91极品视觉盛宴| 国产日韩欧美综合在线| 天堂成人免费av电影一区| 成人激情免费网站| 久久久国产午夜精品| 奇米影视一区二区三区小说| 国产一区二区三区在线观看免费 | 99久久久免费精品国产一区二区| 精品三级在线观看| 婷婷国产在线综合| 欧美色视频在线观看| 亚洲男同性视频| 91免费小视频| 成人欧美一区二区三区在线播放| 国内成人精品2018免费看| 日韩一级欧美一级| 免费看欧美美女黄的网站| 欧美日韩在线不卡| 亚洲曰韩产成在线| 欧美日韩国产小视频| 亚洲成人在线免费| 欧美老女人第四色| 丝袜美腿亚洲综合| 欧美人与禽zozo性伦| 亚洲电影一级黄| 欧美日韩aaaaa| 秋霞电影网一区二区| 欧美亚洲国产bt| 国产又黄又大久久| 综合久久国产九一剧情麻豆| 欧美天天综合网| 精品在线亚洲视频| 亚洲人一二三区| 欧美大片国产精品| 99久久久久免费精品国产| 日韩国产欧美在线视频| 国产欧美一区二区精品性色超碰 | 国产一区二区三区最好精华液| 国产精品久久久久天堂| 欧美精品 国产精品| 国产成人精品亚洲777人妖| 亚洲欧美日韩国产手机在线| 欧美精品在欧美一区二区少妇| 蜜臀久久久99精品久久久久久| 欧美成人综合网站| 成人动漫视频在线| 蜜桃一区二区三区四区| 久久综合中文字幕| 国产精品影视在线| 国产日韩高清在线| 欧美精彩视频一区二区三区| 国产精品理论片| 99久久99久久精品免费观看| 久久色在线观看| 欧美国产精品一区| 欧美美女一区二区在线观看| 亚洲精品你懂的| 99久久伊人精品| 亚洲国产精品av| 97超碰欧美中文字幕| 激情久久久久久久久久久久久久久久| 欧美精品在线视频| 日本欧美在线观看| 欧美高清dvd| 日韩av在线免费观看不卡| 久久成人av少妇免费| 午夜精品福利一区二区三区av | 欧美一区二区三区日韩| 精品国产乱码久久| 欧美视频一区二区三区| 亚洲高清视频在线| 欧美一区二区三区视频| 欧美96一区二区免费视频|