亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解如何使用unsafe標(biāo)準(zhǔn)庫(kù)突破Golang中的類型限制

 更新時(shí)間:2024年03月29日 09:45:25   作者:碼樂(lè)  
在使用c語(yǔ)言編程時(shí),常常因?yàn)轭愋偷膯?wèn)題大傷腦筋,而,golang提供了一些方式用于喜歡hack的用戶,下面我們就來(lái)講講如何使用unsafe標(biāo)準(zhǔn)庫(kù)突破Golang中的類型限制吧

1 簡(jiǎn)介

在使用c語(yǔ)言編程時(shí),常常因?yàn)轭愋偷膯?wèn)題大傷腦筋,而其他語(yǔ)言比如java,python默認(rèn)類型又是難以改變的,golang提供了一些方式用于喜歡hack的用戶。

2 標(biāo)準(zhǔn)庫(kù)unsafe的簡(jiǎn)單介紹

官方說(shuō)明標(biāo)準(zhǔn)庫(kù) unsafe 包含繞過(guò) Go 程序的類型安全的操作。

導(dǎo)入unsafe包可能是不可移植的,并且不受 Go 1 兼容性指南的保護(hù)。

在1.20中,標(biāo)準(zhǔn)庫(kù)的unsafe包很小, 二個(gè)結(jié)構(gòu)體類型,八個(gè)函數(shù),在一個(gè)文件中。

package unsage

    type ArbitraryType int
    type IntegerType int
    type Pointer *ArbitraryType

    func Sizeof(x ArbitraryType) uintptr
    func Offsetof(x ArbitraryType) uintptr
    func Alignof(x ArbitraryType) uintptr

    func Add(ptr Pointer, len IntegerType) Pointer
    func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType
    func SliceData(slice []ArbitraryType) *ArbitraryType
    func String(ptr *byte, len IntegerType) string
    func StringData(str string) *byte

unsafe包定義了 二個(gè)類型和 八個(gè)函數(shù),二個(gè)類型 ArbitraryType 和 IntegerType 不真正屬于unsafe包,我們?cè)贕o代碼中并不能使用它們定義變量。

它表示一個(gè)任意表達(dá)式的類型,僅用于文檔目的,Go編譯器會(huì)對(duì)其做特殊處理。

雖然位于 unsafe,但是 Alignof,Offsetof,Sizeof,這三個(gè)函數(shù)的使用是絕對(duì)安全的。 以至于Go設(shè)計(jì)者Rob pike提議移走它們。

這三個(gè)函數(shù)的共同點(diǎn)是 都返回 uintptr 類型。

之所以使用 uintptr 類型而不是 uint64 整型,因?yàn)檫@三個(gè)函數(shù)更多應(yīng)用于 有 unsafe.Pointer和 uintptr類型參數(shù)的指針運(yùn)算。

采用uintptr做為返回值類型可以減少指針運(yùn)算表達(dá)式的顯式類型轉(zhuǎn)換。

2.1 獲取大小 Sizeof

Sizeof 用于獲取一個(gè)表達(dá)式的大小。 該函數(shù)獲取一個(gè)任意類型的表達(dá)式 x,并返回 按bytes計(jì)算 的大小,假設(shè)變量v,并且v通過(guò) v =x聲明。

Sizeof 接收任何類型的表達(dá)式x,并返回以bytes字節(jié)為單位的大小, 并且假設(shè)變量v是通過(guò)var v = x聲明的。該大小不包括任何可能被x引用的內(nèi)存。

例如,如果x是一個(gè)切片,Sizeof返回切片描述符的大小,而不是該片所引用的內(nèi)存的大小。
對(duì)于一個(gè)結(jié)構(gòu)體,其大小包括由字段對(duì)齊引入的任何填充。

如果參數(shù)x的類型沒(méi)有變化,不具有可變的大小,Sizeof的返回值是一個(gè)Go常數(shù)不可變值 。
(如果一個(gè)類型是一個(gè)類型參數(shù),或者是一個(gè)數(shù)組,則該類型具有可變的大小或結(jié)構(gòu)類型中的元素大小可變)。

示例:

var (
        i  int = 5
        a      = [10]int{}
        ss     = a[:]
        f  FuncFoo

        preValue = map[string]uintptr{
            "i":       8,
            "a":       80,
            "ss":      24,
            "f":       48,
            "f.c":     10,
            "int_nil": 8,
        }
    )

    type FuncFoo struct {
        a int
        b string
        c [10]byte
        d float64
    }
    func TestFuncSizeof(t *testing.T) {
        defer setUp(t.Name())()
        fmt.Printf("\tExecute test:%v\n", t.Name())

        if unsafe.Sizeof(i) != preValue["i"] {
            ErrorHandler(fmt.Sprintf("size: %v not equal %v", unsafe.Sizeof(i), preValue["i"]), t)
        }

        if unsafe.Sizeof(a) != preValue["a"] {
            ErrorHandler(fmt.Sprintf("size: %v not equal %v", unsafe.Sizeof(i), preValue["a"]), t)

        }

        if unsafe.Sizeof(ss) != preValue["ss"] {
            ErrorHandler(fmt.Sprintf("size: %v not equal %v", unsafe.Sizeof(i), preValue["ss"]), t)

        }
        if unsafe.Sizeof(f) != preValue["f"] {
            ErrorHandler(fmt.Sprintf("size: %v not equal %v", unsafe.Sizeof(i), preValue["f"]), t)

        }
        if unsafe.Sizeof(f.c) != preValue["f.c"] {
            ErrorHandler(fmt.Sprintf("size: %v not equal %v", unsafe.Sizeof(i), preValue["f.c"]), t)

        }
        if unsafe.Sizeof(unsafe.Sizeof((*int)(nil))) != preValue["int_nil"] {
            ErrorHandler(fmt.Sprintf("size: %v not equal %v", unsafe.Sizeof(i), preValue["int_nil"]), t)

        }
    }

Sizeof 函數(shù)不支持之間傳入無(wú)類型信息的nil值,如下錯(cuò)誤

unsafe.Sizeof(nil)

我們必須顯式告知 Sizeof 傳入的nil究竟是那個(gè)類型,

unsafe.Sizeof(unsafe.Sizeof((*int)(nil)))

必須顯式告知nil是哪個(gè)類型的nil,這就是傳入一個(gè)值 nil 但是類型明確的變量。

對(duì)齊系數(shù) Alignof 用于獲取一個(gè)表達(dá)式的內(nèi)地地址對(duì)齊系數(shù),對(duì)齊系數(shù) alignment factor 是一個(gè)計(jì)算機(jī)體系架構(gòu) computer architecture 層面的術(shù)語(yǔ)。

在不同計(jì)算機(jī)體系中,處理器對(duì)變量地址都有對(duì)齊要求,即變量的地址必須可被該變量的對(duì)齊系數(shù)整除。

它接收一個(gè)任何類型的表達(dá)式x,并返回所需的排列方式 假設(shè)變量v是通過(guò)var v = x聲明的。
它是m一個(gè)最大的值。

例1,

a      = [10]int{}

        reflect.TypeOf(x).Align()  //8
        unsafe.Alignof(a)   //8

它與reflect.TypeOf(x).Align()返回的值相同。

作為一個(gè)特例,如果一個(gè)變量s是結(jié)構(gòu)類型,f是一個(gè)字段,那么Alignof(s.f)將返回所需的對(duì)齊方式。

該類型的字段在結(jié)構(gòu)中的位置。這種情況與reeflect.TypeOf(s.f).FieldAlign()返回的值。

Alignof的返回值是一個(gè)Go常數(shù),如果參數(shù)的類型不具有可變大小。
(關(guān)于可變大小類型的定義,請(qǐng)參見(jiàn)[Sizeof]的描述)。

繼上 例2:

var (
        i  int = 5
        a      = [10]int{}
        ss     = a[:]
        f  FuncFoo
        zhs = "文"

        preValue = map[string]uintptr{
            "i":       8,
            "a":       80,
            "ss":      24,
            "f":       48,
            "f.c":     10,
            "int_nil": 8,
        }
    )

    func TestAlignof(t *testing.T) {

        defer setUp(t.Name())()
        fmt.Printf("\tExecute test:%v\n", t.Name())

        var x int 

        b := uintptr(unsafe.Pointer(&x))%unsafe.Alignof(x) == 0
        t.Log("alignof:", b)

        if unsafe.Alignof(i) != preValue["i"] {
            ErrorHandler(fmt.Sprintf("Alignof: %v not equal %v", unsafe.Sizeof(i), preValue["int_nil"]), t)

        }

        if unsafe.Alignof(a) != preValue["i"] {
            ErrorHandler(fmt.Sprintf("Alignof: %v not equal %v", unsafe.Sizeof(i), preValue["int_nil"]), t)

        }

        if unsafe.Alignof(ss) != preValue["i"] {
            ErrorHandler(fmt.Sprintf("Alignof: %v not equal %v", unsafe.Sizeof(i), preValue["int_nil"]), t)

        }

        if unsafe.Alignof(f.a) != preValue["i"] {
            ErrorHandler(fmt.Sprintf("Alignof: %v not equal %v", unsafe.Sizeof(i), preValue["int_nil"]), t)

        }

        if unsafe.Alignof(f) != preValue["i"] {
            ErrorHandler(fmt.Sprintf("Alignof: %v not equal %v", unsafe.Sizeof(i), preValue["int_nil"]), t)

        }

中文對(duì)齊系數(shù) 為 8

if unsafe.Alignof(zhs) != preValue["i"] {
            ErrorHandler(fmt.Sprintf("Alignof: %v not equal %v", unsafe.Sizeof(i), preValue["i"]), t)
        }

空結(jié)構(gòu)體對(duì)齊系數(shù) 1

if unsafe.Alignof(struct{}{}) != 1 {
            ErrorHandler(fmt.Sprintf("Alignof: %v not equal %v", unsafe.Sizeof(i), 1), t)
        }

byte 數(shù)組對(duì)齊系數(shù)為 1

if unsafe.Alignof(sbyte) != 1 {
            ErrorHandler(fmt.Sprintf("Alignof: %v not equal %v", unsafe.Sizeof(i), 1), t)
        }

長(zhǎng)度為0 的數(shù)組,與其元素的對(duì)齊系數(shù)相同

if unsafe.Alignof([0]int{}) != 8 {
            ErrorHandler(fmt.Sprintf("Alignof: %v not equal %v", unsafe.Sizeof(i), 8), t)
        }

長(zhǎng)度為0 的數(shù)組,與其元素的對(duì)齊系數(shù)相同

if unsafe.Alignof([0]struct{}{}) != 1 {
            ErrorHandler(fmt.Sprintf("Alignof: %v not equal %v", unsafe.Sizeof(i), 1), t)
        }

    }

執(zhí)行它:

go test -timeout 30s -run ^TestAlignof$ ./unsafe_case.go

對(duì)齊系數(shù) alignment factor,變量的地址必須可被該變量的對(duì)齊系數(shù)整除。

2.2 使用對(duì)齊的例子

我們使用相同字段,分別創(chuàng)建兩個(gè)結(jié)構(gòu)體屬性分別為對(duì)齊或不對(duì)齊,幫助 go 更好地分配內(nèi)存和 使用cpu讀取,查看效果

type RandomResource struct {
        Cloud               string // 16 bytes
        Name                string // 16 bytes
        HaveDSL             bool   //  1 byte
        PluginVersion       string // 16 bytes
        IsVersionControlled bool   //  1 byte
        TerraformVersion    string // 16 bytes
        ModuleVersionMajor  int32  //  4 bytes
    }

    type OrderResource struct {
        ModuleVersionMajor  int32  //  4 bytes
        HaveDSL             bool   //  1 byte
        IsVersionControlled bool   //  1 byte
        Cloud               string // 16 bytes
        Name                string // 16 bytes
        PluginVersion       string // 16 bytes
        TerraformVersion    string // 16 bytes

    }

字段 存儲(chǔ)使用的空間與 字段值沒(méi)有關(guān)系

var d RandomResource
         d.Cloud = "aws-singapore"
         ...

         InfoHandler(fmt.Sprintf("隨機(jī)順序?qū)傩缘慕Y(jié)構(gòu)體內(nèi)存 總共占用 StructType: %T => [%d]\n", d, unsafe.Sizeof(d)), m)
         var te = OrderResource{}
         te.Cloud = "aws-singapore"  
         ...
         m.Logf("屬性對(duì)齊的結(jié)構(gòu)體內(nèi)存 總共占用  StructType:d %T => [%d]\n", te, unsafe.Sizeof(te))

然后復(fù)制結(jié)構(gòu)體,并改變其屬性值,查看存儲(chǔ)空間和值的長(zhǎng)度變化

te2 := te
        te2.Cloud = "ali2"
        m.Logf("結(jié)構(gòu)體2 te2:%#v\n", &te2)
        m.Logf("結(jié)構(gòu)體1 te:%#v\n", &te)

        m.Log("改變 te3 將同時(shí)改變 te,te3 指向了 te的地址")
        m.Log("復(fù)制了對(duì)齊結(jié)構(gòu)體,并重新賦值,用于查看字段長(zhǎng)度。")
        m.Log("(*te).Cloud:", (te).Cloud, "*te.Cloud", te.Cloud, "te size:", unsafe.Sizeof(te.Cloud), "te value len:", len(te.Cloud))

        te3 := &te
        te3.Cloud = "HWCloud2"

        m.Log("(*te3).Cloud:", (*te3).Cloud, "*te3.Cloud", te3.Cloud, "te3 size:", unsafe.Sizeof(te3.Cloud), "te3 value len:", len(te3.Cloud))
        m.Logf("字段 Cloud:%v te3:%p\n", (*te3).Cloud, te3)
        m.Logf("字段 Cloud:%v order:%v te:%v, addr:%p\n", te.Cloud, (te).Cloud, te, &te)

執(zhí)行它,

go test -v .\case_test.go

得到以下輸出:

隨機(jī)順序?qū)傩缘慕Y(jié)構(gòu)體內(nèi)存 總共占用 StructType: main.Raesource => [88]

屬性對(duì)齊的結(jié)構(gòu)體內(nèi)存 總共占用 StructType:d main.OrderResource => [72]

改變 te3 將同時(shí)改變 te,te3 指向了 te的地址

case_test.go:186: 復(fù)制了對(duì)齊結(jié)構(gòu)體,并重新賦值,用于查看字段長(zhǎng)度。

    case_test.go:188: (*te).Cloud: aws-singapore *te.Cloud aws-singapore te size: 16 te Alignof: 8 te value len: 13 reflect Align len and field Align len: 8 8
    case_test.go:190: (*te2).Cloud: ali2 *te2.Cloud aws-singapore te2 size: 16 te2 Alignof: 8 te2 value len: 4 reflect Align len and field Align len: 8 8
    case_test.go:196: (*te3).Cloud: HWCloud2-asia-southeast-from-big-plant-place-air-local-video-service-picture-merge-from-other-all-company *te3.Cloud HWCloud2-asia-southeast-from-big-plant-place-air-local-video-service-picture-merge-from-other-all-company te3 
size: 16 te3 Alignof: 8 te3 value len: 105 reflect Align len and field Align len: 8 8

    case_test.go: 結(jié)構(gòu)體1字段 Cloud:HWCloud2-asia-southeast-from-big-plant-place-air-local-video-service-picture-merge-from-other-all-company te2:0xc0000621e0
    case_test.go:198: 結(jié)構(gòu)體2字段 Cloud:ali2 te2:0xc000062280
    case_test.go:199: 結(jié)構(gòu)體3字段 Cloud:HWCloud2-asia-southeast-from-big-plant-place-air-local-video-service-picture-merge-from-other-all-company te3:0xc0000621e0

小結(jié)

我們介紹了unsafe包的檢查功能,在初始化時(shí),go結(jié)構(gòu)體已經(jīng)分配了對(duì)于的內(nèi)存空間,

一個(gè)結(jié)構(gòu)體而言,結(jié)構(gòu)體屬性為隨機(jī)順序的,go將分配更多內(nèi)存空間。 即使是復(fù)制后。

比如 結(jié)構(gòu)體的Cloud 字段。

Sizeof表達(dá)式大小總是16,

而對(duì)齊系數(shù) Alignof 大小總是8,

而在不同的結(jié)構(gòu)體實(shí)例中值長(zhǎng)度可以為 4,13, 105.

本節(jié)源碼地址:https://github.com/hahamx/examples/tree/main/alg_practice/2_sys_io

到此這篇關(guān)于詳解如何使用unsafe標(biāo)準(zhǔn)庫(kù)突破Golang中的類型限制的文章就介紹到這了,更多相關(guān)Go unsafe內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang如何使用指針靈活操作內(nèi)存及unsafe包原理解析

    golang如何使用指針靈活操作內(nèi)存及unsafe包原理解析

    本文將深入探討unsafe包的功能和原理,同時(shí),我們學(xué)習(xí)某種東西,一方面是為了實(shí)踐運(yùn)用,另一方面則是出于功利性面試的目的,所以,本文還會(huì)為大家介紹unsafe?包的典型應(yīng)用以及高頻面試題,感興趣的朋友跟隨小編一起看看吧
    2024-07-07
  • 輕松入門:使用Golang開發(fā)跨平臺(tái)GUI應(yīng)用

    輕松入門:使用Golang開發(fā)跨平臺(tái)GUI應(yīng)用

    Golang是一種強(qiáng)大的編程語(yǔ)言,它的并發(fā)性和高性能使其成為開發(fā)GUI桌面應(yīng)用的理想選擇,Golang提供了豐富的標(biāo)準(zhǔn)庫(kù)和第三方庫(kù),可以輕松地創(chuàng)建跨平臺(tái)的GUI應(yīng)用程序,通過(guò)使用Golang的GUI庫(kù),開發(fā)人員可以快速構(gòu)建具有豐富用戶界面和交互功能的應(yīng)用程序,需要的朋友可以參考下
    2023-10-10
  • Golang中正則表達(dá)式語(yǔ)法及相關(guān)示例

    Golang中正則表達(dá)式語(yǔ)法及相關(guān)示例

    正則表達(dá)式是一種用于匹配和操作文本的強(qiáng)大工具,它使用特殊的字符和語(yǔ)法來(lái)定義模式,下面這篇文章主要給大家介紹了關(guān)于Golang中正則表達(dá)式語(yǔ)法及相關(guān)示例的相關(guān)資料,需要的朋友可以參考下
    2024-05-05
  • 從并發(fā)到并行解析Go語(yǔ)言中的sync.WaitGroup

    從并發(fā)到并行解析Go語(yǔ)言中的sync.WaitGroup

    Go?語(yǔ)言提供了許多工具和機(jī)制來(lái)實(shí)現(xiàn)并發(fā)編程,其中之一就是?sync.WaitGroup。本文就來(lái)深入討論?sync.WaitGroup,探索其工作原理和在實(shí)際應(yīng)用中的使用方法吧
    2023-05-05
  • 用golang實(shí)現(xiàn)一個(gè)定時(shí)器任務(wù)隊(duì)列實(shí)例

    用golang實(shí)現(xiàn)一個(gè)定時(shí)器任務(wù)隊(duì)列實(shí)例

    golang中提供了2種定時(shí)器timer和ticker,分別是一次性定時(shí)器和重復(fù)任務(wù)定時(shí)器。這篇文章主要介紹了用golang實(shí)現(xiàn)一個(gè)定時(shí)器任務(wù)隊(duì)列實(shí)例,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2018-05-05
  • 使用Golang實(shí)現(xiàn)流式輸出

    使用Golang實(shí)現(xiàn)流式輸出

    這篇文章主要為大家詳細(xì)介紹了使用Golang實(shí)現(xiàn)流式輸出的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-03-03
  • Go 語(yǔ)言中的 http.FileSystem詳細(xì)解析

    Go 語(yǔ)言中的 http.FileSystem詳細(xì)解析

    在本文中,我們深入探討了 Go 語(yǔ)言中的 http.FileSystem 接口,并介紹了它的基本原理、使用方法以及實(shí)際應(yīng)用場(chǎng)景,感興趣的朋友跟隨小編一起看看吧
    2024-03-03
  • Go語(yǔ)言工程實(shí)踐單元測(cè)試基準(zhǔn)測(cè)試示例詳解

    Go語(yǔ)言工程實(shí)踐單元測(cè)試基準(zhǔn)測(cè)試示例詳解

    這篇文章主要為大家介紹了Go語(yǔ)言工程實(shí)踐單元測(cè)試基準(zhǔn)測(cè)試示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • Golang設(shè)計(jì)模式之適配器模式介紹和代碼示例

    Golang設(shè)計(jì)模式之適配器模式介紹和代碼示例

    適配器是一種結(jié)構(gòu)型設(shè)計(jì)模式, 它能使不兼容的對(duì)象能夠相互合作,可擔(dān)任兩個(gè)對(duì)象間的封裝器, 它會(huì)接收對(duì)于一個(gè)對(duì)象的調(diào)用, 并將其轉(zhuǎn)換為另一個(gè)對(duì)象可識(shí)別的格式和接口,本文將通過(guò)代碼示例詳細(xì)給大家介紹Golang的適配器模式
    2023-06-06
  • Go?實(shí)戰(zhàn)單隊(duì)列到優(yōu)先級(jí)隊(duì)列實(shí)現(xiàn)圖文示例

    Go?實(shí)戰(zhàn)單隊(duì)列到優(yōu)先級(jí)隊(duì)列實(shí)現(xiàn)圖文示例

    這篇文章主要為大家介紹了Go?實(shí)戰(zhàn)單隊(duì)列到優(yōu)先級(jí)隊(duì)列圖文示例實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07

最新評(píng)論