コンテンツにスキップ

Go/uint32

出典: フリー教科書『ウィキブックス(Wikibooks)』
< Go

Goのuint32について

[編集]

Goにおけるuint32は32ビット符号なし整数型を表す事前宣言された型です。4バイトのサイズを持ち、0から4294967295までの値を格納できます。

基本情報

[編集]
  • uint32は32ビット(4バイト)の符号なし整数型
  • 値の範囲: 0 から 4294967295 (2^32-1)
  • メモリ上での表現: 32ビット
  • IPアドレス、ファイルサイズ、タイムスタンプなどの表現によく使用される

他のキーワードとの組み合わせ

[編集]

変数宣言との組み合わせ

[編集]
var fileSize uint32 = 1048576
count := uint32(100000) // 型推論による短縮形
maxValue := uint32(4294967295)

定数定義との組み合わせ

[編集]
const MAX_FILE_SIZE uint32 = 100 * 1024 * 1024 // 100MB
const BUFFER_SIZE uint32 = 65536
const EPOCH_OFFSET uint32 = 2208988800 // Unix epoch offset

関数パラメータと戻り値

[編集]
func calculateChecksum(data []byte) uint32 {
    var sum uint32
    for _, b := range data {
        sum += uint32(b)
    }
    return sum
}

func getCurrentTimestamp() uint32 {
    return uint32(time.Now().Unix())
}

型変換

[編集]
i := 1000000
size := uint32(i) // int から uint32 への変換

f := 3.14159265359
rounded := uint32(f) // float から uint32 への変換(小数点以下切り捨て)

// より大きな型からの変換
var bigNum uint64 = 5000000000
smallNum := uint32(bigNum) // 値が範囲外の場合は下位32ビットのみが保持される

配列とスライス

[編集]
var sizes [100]uint32 // uint32型の固定長配列
buffer := make([]uint32, 1024) // uint32型のスライス
timestamps := []uint32{1609459200, 1640995200, 1672531200} // リテラルで初期化

マップ

[編集]
fileSizes := make(map[string]uint32)
fileSizes["document.pdf"] = 2048576
fileSizes["image.jpg"] = 1024000
fileSizes["video.mp4"] = 104857600

ipToID := make(map[uint32]string)
ipToID[3232235521] = "192.168.1.1"

構造体のフィールド

[編集]
type FileInfo struct {
    Name         string
    Size         uint32
    CreatedAt    uint32 // Unix timestamp
    Permissions  uint32
}

type IPv4Address struct {
    Address uint32 // IPv4アドレスを32ビット整数で表現
}

ビット操作

[編集]
var flags uint32 = 0
// ビットをセット
flags |= 1 << 16
// ビットをクリア
flags &^= 1 << 10
// ビットをチェック
if (flags & (1 << 16)) != 0 {
    fmt.Println("16番目のビットがセットされています")
}

// 32ビットを4つの8ビットに分割
var value uint32 = 0x12345678
byte1 := uint8(value >> 24)        // 0x12
byte2 := uint8((value >> 16) & 0xFF) // 0x34
byte3 := uint8((value >> 8) & 0xFF)  // 0x56
byte4 := uint8(value & 0xFF)         // 0x78

一般的なユースケース

[編集]
  1. ファイルサイズとディスク容量管理
       type FileSystem struct {
           TotalSpace uint32 // バイト単位
           UsedSpace  uint32
           FreeSpace  uint32
       }
       
       func (fs *FileSystem) AddFile(size uint32) error {
           if fs.FreeSpace < size {
               return fmt.Errorf("insufficient space")
           }
           fs.UsedSpace += size
           fs.FreeSpace -= size
           return nil
       }
       
       func formatBytes(bytes uint32) string {
           const unit = 1024
           if bytes < unit {
               return fmt.Sprintf("%d B", bytes)
           }
           div, exp := uint32(unit), 0
           for n := bytes / unit; n >= unit; n /= unit {
               div *= unit
               exp++
           }
           return fmt.Sprintf("%.1f %cB", float64(bytes)/float64(div), "KMGTPE"[exp])
       }
    
  2. IPv4アドレス処理
       import (
           "encoding/binary"
           "net"
       )
       
       func ipToUint32(ip net.IP) uint32 {
           ip = ip.To4()
           if ip == nil {
               return 0
           }
           return binary.BigEndian.Uint32(ip)
       }
       
       func uint32ToIP(n uint32) net.IP {
           ip := make(net.IP, 4)
           binary.BigEndian.PutUint32(ip, n)
           return ip
       }
       
       func isInSubnet(ip, network, mask uint32) bool {
           return (ip & mask) == (network & mask)
       }
       
       // 使用例
       func main() {
           ip := net.ParseIP("192.168.1.100")
           ipNum := ipToUint32(ip)
           fmt.Printf("IP: %s, Numeric: %d\n", ip, ipNum)
           
           // サブネットチェック
           network := ipToUint32(net.ParseIP("192.168.1.0"))
           mask := uint32(0xFFFFFF00) // /24
           if isInSubnet(ipNum, network, mask) {
               fmt.Println("IP is in subnet")
           }
       }
    
  3. Unixタイムスタンプ
       type Event struct {
           ID        uint32
           Name      string
           Timestamp uint32 // Unix timestamp
       }
       
       func CreateEvent(name string) Event {
           return Event{
               ID:        generateID(),
               Name:      name,
               Timestamp: uint32(time.Now().Unix()),
           }
       }
       
       func (e Event) ToTime() time.Time {
           return time.Unix(int64(e.Timestamp), 0)
       }
       
       func (e Event) IsExpired(ttlSeconds uint32) bool {
           current := uint32(time.Now().Unix())
           return current > e.Timestamp+ttlSeconds
       }
    
  4. ハッシュ値とチェックサム
       import (
           "hash/crc32"
           "hash/fnv"
       )
       
       func calculateCRC32(data []byte) uint32 {
           return crc32.ChecksumIEEE(data)
       }
       
       func calculateFNV32(data []byte) uint32 {
           h := fnv.New32a()
           h.Write(data)
           return h.Sum32()
       }
       
       type DataBlock struct {
           Data     []byte
           Checksum uint32
       }
       
       func NewDataBlock(data []byte) DataBlock {
           return DataBlock{
               Data:     data,
               Checksum: calculateCRC32(data),
           }
       }
       
       func (db DataBlock) Verify() bool {
           return db.Checksum == calculateCRC32(db.Data)
       }
    
  5. メモリプールとオブジェクト管理
       type ObjectPool struct {
           objects    map[uint32]interface{}
           nextID     uint32
           freeIDs    []uint32
           maxObjects uint32
       }
       
       func NewObjectPool(maxObjects uint32) *ObjectPool {
           return &ObjectPool{
               objects:    make(map[uint32]interface{}),
               nextID:     1,
               freeIDs:    make([]uint32, 0),
               maxObjects: maxObjects,
           }
       }
       
       func (pool *ObjectPool) Allocate(obj interface{}) (uint32, error) {
           if uint32(len(pool.objects)) >= pool.maxObjects {
               return 0, fmt.Errorf("pool is full")
           }
           
           var id uint32
           if len(pool.freeIDs) > 0 {
               id = pool.freeIDs[len(pool.freeIDs)-1]
               pool.freeIDs = pool.freeIDs[:len(pool.freeIDs)-1]
           } else {
               id = pool.nextID
               pool.nextID++
           }
           
           pool.objects[id] = obj
           return id, nil
       }
       
       func (pool *ObjectPool) Free(id uint32) {
           if _, exists := pool.objects[id]; exists {
               delete(pool.objects, id)
               pool.freeIDs = append(pool.freeIDs, id)
           }
       }
    
  6. バイナリプロトコルとシリアライゼーション
       import "encoding/binary"
       
       type Header struct {
           Magic     uint32
           Version   uint32
           Length    uint32
           Flags     uint32
           Timestamp uint32
       }
       
       func (h Header) Serialize() []byte {
           buf := make([]byte, 20) // 5 * 4 bytes
           binary.LittleEndian.PutUint32(buf[0:], h.Magic)
           binary.LittleEndian.PutUint32(buf[4:], h.Version)
           binary.LittleEndian.PutUint32(buf[8:], h.Length)
           binary.LittleEndian.PutUint32(buf[12:], h.Flags)
           binary.LittleEndian.PutUint32(buf[16:], h.Timestamp)
           return buf
       }
       
       func DeserializeHeader(data []byte) Header {
           if len(data) < 20 {
               return Header{}
           }
           return Header{
               Magic:     binary.LittleEndian.Uint32(data[0:4]),
               Version:   binary.LittleEndian.Uint32(data[4:8]),
               Length:    binary.LittleEndian.Uint32(data[8:12]),
               Flags:     binary.LittleEndian.Uint32(data[12:16]),
               Timestamp: binary.LittleEndian.Uint32(data[16:20]),
           }
       }
    
  7. カウンターとメトリクス
       type SystemMetrics struct {
           RequestCount    uint32
           ErrorCount      uint32
           BytesProcessed  uint32
           UpTimeSeconds   uint32
       }
       
       func (m *SystemMetrics) IncrementRequests() {
           if m.RequestCount < 4294967295 {
               m.RequestCount++
           }
       }
       
       func (m *SystemMetrics) AddBytesProcessed(bytes uint32) {
           // オーバーフロー対策
           if m.BytesProcessed > 4294967295-bytes {
               m.BytesProcessed = 4294967295
           } else {
               m.BytesProcessed += bytes
           }
       }
       
       func (m SystemMetrics) GetErrorRate() float64 {
           if m.RequestCount == 0 {
               return 0.0
           }
           return float64(m.ErrorCount) / float64(m.RequestCount)
       }
    
  8. ゲーム開発でのリソース管理
       type GameResource struct {
           ID          uint32
           Type        string
           LoadedAt    uint32 // timestamp
           MemoryUsage uint32 // bytes
           RefCount    uint32
       }
       
       type ResourceManager struct {
           resources map[uint32]*GameResource
           nextID    uint32
           totalMemory uint32
           maxMemory   uint32
       }
       
       func NewResourceManager(maxMemory uint32) *ResourceManager {
           return &ResourceManager{
               resources:   make(map[uint32]*GameResource),
               nextID:      1,
               maxMemory:   maxMemory,
           }
       }
       
       func (rm *ResourceManager) LoadResource(resourceType string, memoryUsage uint32) (uint32, error) {
           if rm.totalMemory+memoryUsage > rm.maxMemory {
               return 0, fmt.Errorf("insufficient memory")
           }
           
           resource := &GameResource{
               ID:          rm.nextID,
               Type:        resourceType,
               LoadedAt:    uint32(time.Now().Unix()),
               MemoryUsage: memoryUsage,
               RefCount:    1,
           }
           
           rm.resources[rm.nextID] = resource
           rm.totalMemory += memoryUsage
           rm.nextID++
           
           return resource.ID, nil
       }
       
       func (rm *ResourceManager) UnloadResource(id uint32) {
           if resource, exists := rm.resources[id]; exists {
               rm.totalMemory -= resource.MemoryUsage
               delete(rm.resources, id)
           }
       }
    

注意点

[編集]
  1. オーバーフロー: 最大値(4294967295)を超えると、0に戻ります(ラップアラウンド)
       var x uint32 = 4294967295
       x++ // x は 0 になる
       
       // オーバーフロー対策
       func safeAdd(a, b uint32) (uint32, bool) {
           if a > 4294967295-b {
               return 0, false // オーバーフロー
           }
           return a + b, true
       }
    
  2. 負の値: 負の値を代入しようとするとコンパイルエラーになります
       var size uint32 = -1 // コンパイルエラー
    
  3. 範囲外の値: 代入時に自動的に切り捨てられます
       var large uint64 = 5000000000
       var small uint32 = uint32(large) // 5000000000 % 4294967296 = 705032704
    
  4. 演算時の型の考慮: より大きな型との演算では型変換が必要な場合があります
       var a uint32 = 2000000000
       var b uint32 = 2000000000
       // var sum = a + b // オーバーフローの可能性
       
       // 安全な演算
       sum64 := uint64(a) + uint64(b)
       if sum64 > 4294967295 {
           fmt.Println("オーバーフローが発生しました")
       }
    
  5. Unixタイムスタンプの制限: uint32のUnixタイムスタンプは2038年問題があります
       // 2038年1月19日3:14:07 UTCでオーバーフロー
       var maxUnixTime uint32 = 2147483647
       
       // 2038年問題を回避するには、int64またはtime.Timeを使用
       func getCurrentTimestamp64() int64 {
           return time.Now().Unix()
       }
    
  6. プラットフォーム依存性: 異なるアーキテクチャ間でのバイト順序に注意
       import "encoding/binary"
       
       func writeUint32(w io.Writer, value uint32, order binary.ByteOrder) error {
           buf := make([]byte, 4)
           order.PutUint32(buf, value)
           _, err := w.Write(buf)
           return err
       }
    

uint32型は、ファイルサイズ、IPアドレス、タイムスタンプ、大きなカウンター、ハッシュ値など、広範囲の数値を効率的に扱う場合に適しています。大きな数値を扱う際は、オーバーフローや2038年問題などの制限に注意して使用することが重要です。