亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

搜索

Go語言中uint64的存儲:固定內存分配與變長編碼解析

DDD
發(fā)布: 2025-10-17 10:12:47
原創(chuàng)
355人瀏覽過

Go語言中uint64的存儲:固定內存分配與變長編碼解析

go語言中,`uint64`類型變量在內存中始終占用8字節(jié)的固定空間。然而,當使用`binary.putuvarint`等函數(shù)進行序列化時,`uint64`值可能被編碼為多達10字節(jié)的變長數(shù)據(jù)。這種差異源于go的varint編碼設計,它優(yōu)先考慮編碼格式的通用性和一致性,而非在特定情況下最小化64位值的字節(jié)數(shù)。

在Go語言的開發(fā)實踐中,理解基本數(shù)據(jù)類型在內存中的存儲方式以及它們在不同場景下的編碼表現(xiàn)至關重要。特別是對于uint64這種大整數(shù)類型,其內存占用與序列化編碼之間存在著值得深入探討的差異。

Go語言中uint64的固定內存分配

Go語言規(guī)范明確定義了各種基本數(shù)據(jù)類型在內存中的固定大小。對于uint64類型,無論其存儲的數(shù)值大小如何(從0到2^64-1),它在內存中始終占用8個字節(jié)。這是Go語言為了保證內存訪問效率和可預測性而做出的設計選擇。

根據(jù)Go語言官方文檔Size and alignment guarantees的規(guī)定,常見類型的大小如下:

type                                 size in bytes

byte, uint8, int8                     1
uint16, int16                         2
uint32, int32, float32                4
uint64, int64, float64, complex64     8
complex128                           16
登錄后復制

這意味著,當你聲明一個uint64類型的變量時,系統(tǒng)會為其分配8字節(jié)的內存空間,這個空間大小是固定的,與變量實際存儲的數(shù)值無關。例如,uint64(1)和uint64(math.MaxUint64)在內存中都占用8字節(jié)。

立即學習go語言免費學習筆記(深入)”;

我們可以通過unsafe.Sizeof函數(shù)來驗證這一點:

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    var u64_small uint64 = 1
    var u64_large uint64 = ^uint64(0) // Max uint64 value (2^64 - 1)

    fmt.Printf("變量 u64_small (%d) 在內存中占用 %d 字節(jié)\n", u64_small, unsafe.Sizeof(u64_small))
    fmt.Printf("變量 u64_large (%d) 在內存中占用 %d 字節(jié)\n", u64_large, unsafe.Sizeof(u64_large))
}
登錄后復制

運行上述代碼,會輸出:

變量 u64_small (1) 在內存中占用 8 字節(jié)
變量 u64_large (18446744073709551615) 在內存中占用 8 字節(jié)
登錄后復制

這清晰地表明了uint64在內存中的固定大小特性。

binary.PutUvarint的變長編碼(Varint)

盡管uint64在內存中是固定8字節(jié),但在數(shù)據(jù)序列化(例如,網(wǎng)絡傳輸、文件存儲)的場景中,Go語言提供了變長編碼(Varint)機制,以實現(xiàn)更高效的空間利用。encoding/binary包中的PutUvarint函數(shù)就是用于將uint64值編碼為變長字節(jié)序列的。

Varint編碼的原理是:對于較小的數(shù)值,使用較少的字節(jié)表示;對于較大的數(shù)值,則使用更多的字節(jié)。這種編碼方式在數(shù)據(jù)分布集中于較小數(shù)值時,能顯著節(jié)省存儲空間。

然而,一個有趣的現(xiàn)象是,binary.PutUvarint在編碼一個uint64值時,最多可能占用10個字節(jié),這超出了uint64本身的8字節(jié)內存大小。這并非設計錯誤,而是Go語言為了保持編碼格式的通用性和一致性而做出的權衡。

存了個圖
存了個圖

視頻圖片解析/字幕/剪輯,視頻高清保存/圖片源圖提取

存了個圖17
查看詳情 存了個圖

Go標準庫的encoding/binary包中的設計說明解釋了這一決策:

// Design note:
// At most 10 bytes are needed for 64-bit values. The encoding could
// be more dense: a full 64-bit value needs an extra byte just to hold bit 63.
// Instead, the msb of the previous byte could be used to hold bit 63 since we
// know there can't be more than 64 bits. This is a trivial improvement and
// would reduce the maximum encoding length to 9 bytes. However, it breaks the
// invariant that the msb is always the "continuation bit" and thus makes the
// format incompatible with a varint encoding for larger numbers (say 128-bit).
登錄后復制

這段說明揭示了關鍵點:

  1. 最大10字節(jié):對于64位值,最多需要10個字節(jié)進行編碼。
  2. “延續(xù)位”(Continuation Bit)的不變性:Go的varint編碼方案中,每個字節(jié)的最高有效位(MSB)被用作“延續(xù)位”。如果MSB為1,表示當前數(shù)字還有后續(xù)字節(jié);如果MSB為0,表示這是數(shù)字的最后一個字節(jié)。
  3. 設計權衡:為了保持這種“延續(xù)位”不變性,并使編碼格式能夠兼容未來可能出現(xiàn)的更大數(shù)字(如128位),Go選擇了一種在某些情況下(尤其是當uint64的第63位被設置時)會使用額外一個字節(jié)的方案。如果為了將最大編碼長度縮減到9字節(jié)而破壞了這種不變性,將導致格式不兼容。

因此,binary.PutUvarint的10字節(jié)最大長度是其設計哲學的一部分,即優(yōu)先保證編碼格式的通用性和擴展性,而非在所有情況下都追求極致的字節(jié)效率。

示例:binary.PutUvarint的編碼行為

以下代碼演示了binary.PutUvarint如何根據(jù)數(shù)值大小使用不同數(shù)量的字節(jié)進行編碼:

package main

import (
    "encoding/binary"
    "fmt"
)

func main() {
    fmt.Println("--- binary.PutUvarint 變長編碼示例 ---")

    // 較小的 uint64 值 (通常占用1個字節(jié))
    val1 := uint64(150)
    buf1 := make([]byte, binary.MaxVarintLen64) // MaxVarintLen64 is 10
    n1 := binary.PutUvarint(buf1, val1)
    fmt.Printf("編碼值 %d (0x%x): 占用 %d 字節(jié), 編碼結果: %x\n", val1, val1, n1, buf1[:n1])

    // 中等大小的 uint64 值
    val2 := uint64(123456789)
    buf2 := make([]byte, binary.MaxVarintLen64)
    n2 := binary.PutUvarint(buf2, val2)
    fmt.Printf("編碼值 %d (0x%x): 占用 %d 字節(jié), 編碼結果: %x\n", val2, val2, n2, buf2[:n2])

    // 接近最大值的 uint64 值,且最高位(第63位)被設置
    // 2^63 - 1 (會占用9字節(jié))
    val3 := uint64(1<<63 - 1)
    buf3 := make([]byte, binary.MaxVarintLen64)
    n3 := binary.PutUvarint(buf3, val3)
    fmt.Printf("編碼值 %d (0x%x): 占用 %d 字節(jié), 編碼結果: %x\n", val3, val3, n3, buf3[:n3])

    // 最大 uint64 值 (2^64 - 1),會占用10字節(jié)
    val4 := ^uint64(0) // 2^64 - 1
    buf4 := make([]byte, binary.MaxVarintLen64)
    n4 := binary.PutUvarint(buf4, val4)
    fmt.Printf("編碼值 %d (0x%x): 占用 %d 字節(jié), 編碼結果: %x\n", val4, val4, n4, buf4[:n4])

    // 一個會占用10字節(jié)的例子 (通常是高位bit被設置的值)
    val5 := uint64(1<<63) // 2^63
    buf5 := make([]byte, binary.MaxVarintLen64)
    n5 := binary.PutUvarint(buf5, val5)
    fmt.Printf("編碼值 %d (0x%x): 占用 %d 字節(jié), 編碼結果: %x\n", val5, val5, n5, buf5[:n5])
}
登錄后復制

運行上述代碼,你將觀察到不同數(shù)值的uint64被編碼成不同長度的字節(jié)序列,其中最大值或高位被設置的值會占用10字節(jié)。

總結與注意事項

通過上述分析,我們可以得出以下關鍵結論:

  • 內存存儲:Go語言中uint64類型變量在內存中始終占用8字節(jié)的固定空間。這是由Go語言規(guī)范保證的,與數(shù)值大小無關。
  • 序列化編碼:當使用binary.PutUvarint等函數(shù)進行變長編碼時,uint64值可能被編碼為1到10個字節(jié)。這種變長編碼是為了節(jié)省存儲空間,其最大10字節(jié)的長度是Go語言在編碼通用性與字節(jié)效率之間權衡的結果。

在實際開發(fā)中,理解這兩種不同的“大小”概念至關重要:

  • 當你考慮內存布局、結構體大小或數(shù)組元素大小時,應關注uint64的固定8字節(jié)。
  • 當你進行數(shù)據(jù)序列化、網(wǎng)絡傳輸或文件存儲時,應關注binary.PutUvarint等函數(shù)生成的變長編碼大小,尤其是在設計數(shù)據(jù)協(xié)議或計算傳輸開銷時。

正確區(qū)分這兩種存儲和編碼方式,有助于編寫出更高效、更健壯的Go程序。

以上就是Go語言中uint64的存儲:固定內存分配與變長編碼解析的詳細內容,更多請關注php中文網(wǎng)其它相關文章!

最佳 Windows 性能的頂級免費優(yōu)化軟件
最佳 Windows 性能的頂級免費優(yōu)化軟件

每個人都需要一臺速度更快、更穩(wěn)定的 PC。隨著時間的推移,垃圾文件、舊注冊表數(shù)據(jù)和不必要的后臺進程會占用資源并降低性能。幸運的是,許多工具可以讓 Windows 保持平穩(wěn)運行。

下載
來源:php中文網(wǎng)
本文內容由網(wǎng)友自發(fā)貢獻,版權歸原作者所有,本站不承擔相應法律責任。如您發(fā)現(xiàn)有涉嫌抄襲侵權的內容,請聯(lián)系admin@php.cn
最新問題
開源免費商場系統(tǒng)廣告
最新下載
更多>
網(wǎng)站特效
網(wǎng)站源碼
網(wǎng)站素材
前端模板
關于我們 免責申明 意見反饋 講師合作 廣告合作 最新更新
php中文網(wǎng):公益在線php培訓,幫助PHP學習者快速成長!
關注服務號 技術交流群
PHP中文網(wǎng)訂閱號
每天精選資源文章推送
PHP中文網(wǎng)APP
隨時隨地碎片化學習
PHP中文網(wǎng)抖音號
發(fā)現(xiàn)有趣的

Copyright 2014-2025 http://ipnx.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號