Go/uint64

Goのuint64について

Goにおけるuint64は64ビット符号なし整数型を表す組み込み型です。8バイトのサイズを持ち、0から18446744073709551615までの値を格納できます。

基本情報

  • uint64は64ビット(8バイト)の符号なし整数型
  • 値の範囲: 0 から 18446744073709551615 (2^64-1)
  • メモリ上での表現: 64ビット
  • 大容量データサイズ、高精度タイムスタンプ、一意ID生成などに使用される

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

変数宣言との組み合わせ

var totalBytes uint64 = 1099511627776 // 1TB
count := uint64(1000000000) // 型推論による短縮形
maxValue := uint64(18446744073709551615)

定数定義との組み合わせ

const BYTES_PER_KB uint64 = 1024
const BYTES_PER_MB uint64 = 1024 * 1024
const BYTES_PER_GB uint64 = 1024 * 1024 * 1024
const BYTES_PER_TB uint64 = 1024 * 1024 * 1024 * 1024
const NANOSECONDS_PER_SECOND uint64 = 1000000000

関数パラメータと戻り値

func calculateTotalSize(files []FileInfo) uint64 {
    var total uint64
    for _, file := range files {
        total += file.Size
    }
    return total
}

func getCurrentNanoseconds() uint64 {
    return uint64(time.Now().UnixNano())
}

型変換

i := 1000000000000
size := uint64(i) // int から uint64 への変換

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

// 時間関連の変換
duration := time.Minute
nanos := uint64(duration.Nanoseconds())

配列とスライス

var timestamps [1000]uint64 // uint64型の固定長配列
buffer := make([]uint64, 10000) // uint64型のスライス
sizes := []uint64{1073741824, 2147483648, 4294967296} // GB単位のサイズ

マップ

fileSizes := make(map[string]uint64)
fileSizes["large_dataset.csv"] = 10737418240 // 10GB
fileSizes["backup.tar.gz"] = 53687091200    // 50GB

userIDs := make(map[uint64]string)
userIDs[1234567890123456789] = "user@example.com"

構造体のフィールド

type StorageInfo struct {
    DeviceName  string
    TotalSpace  uint64 // バイト単位
    UsedSpace   uint64
    FreeSpace   uint64
    InodeCount  uint64
}

type LogEntry struct {
    ID          uint64 // 一意識別子
    Timestamp   uint64 // ナノ秒精度のタイムスタンプ
    UserID      uint64
    EventSize   uint64 // バイト単位
}

ビット操作

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

// 64ビットを8つの8ビットに分割
var value uint64 = 0x123456789ABCDEF0
bytes := [8]uint8{
    uint8(value >> 56),
    uint8(value >> 48),
    uint8(value >> 40),
    uint8(value >> 32),
    uint8(value >> 24),
    uint8(value >> 16),
    uint8(value >> 8),
    uint8(value),
}

一般的なユースケース

  1. 大容量ストレージ管理
       type DiskUsage struct {
           Path       string
           TotalBytes uint64
           UsedBytes  uint64
           FreeBytes  uint64
       }
       
       func GetDiskUsage(path string) (DiskUsage, error) {
           var stat syscall.Statfs_t
           err := syscall.Statfs(path, &stat)
           if err != nil {
               return DiskUsage{}, err
           }
           
           total := uint64(stat.Blocks) * uint64(stat.Bsize)
           free := uint64(stat.Bavail) * uint64(stat.Bsize)
           used := total - free
           
           return DiskUsage{
               Path:       path,
               TotalBytes: total,
               UsedBytes:  used,
               FreeBytes:  free,
           }, nil
       }
       
       func FormatBytes(bytes uint64) string {
           const unit = 1024
           if bytes < unit {
               return fmt.Sprintf("%d B", bytes)
           }
           
           div, exp := uint64(unit), 0
           for n := bytes / unit; n >= unit; n /= unit {
               div *= unit
               exp++
           }
           return fmt.Sprintf("%.2f %ciB", float64(bytes)/float64(div), "KMGTPE"[exp])
       }
    
  2. 高精度タイムスタンプ
       type HighPrecisionEvent struct {
           ID                uint64
           Name              string
           TimestampNanos    uint64 // ナノ秒精度
           DurationNanos     uint64
       }
       
       func NewEvent(name string) HighPrecisionEvent {
           return HighPrecisionEvent{
               ID:             generateEventID(),
               Name:           name,
               TimestampNanos: uint64(time.Now().UnixNano()),
           }
       }
       
       func (e *HighPrecisionEvent) Finish() {
           endTime := uint64(time.Now().UnixNano())
           e.DurationNanos = endTime - e.TimestampNanos
       }
       
       func (e HighPrecisionEvent) ToTime() time.Time {
           return time.Unix(0, int64(e.TimestampNanos))
       }
       
       func (e HighPrecisionEvent) GetDuration() time.Duration {
           return time.Duration(e.DurationNanos)
       }
       
       // ベンチマーク用途での使用例
       func BenchmarkFunction(fn func()) (uint64, error) {
           start := uint64(time.Now().UnixNano())
           fn()
           end := uint64(time.Now().UnixNano())
           return end - start, nil
       }
    
  3. 一意ID生成(Snowflake ID パターン)
       import (
           "sync"
           "time"
       )
       
       type SnowflakeIDGenerator struct {
           mutex       sync.Mutex
           epoch       uint64  // カスタムエポック (ミリ秒)
           nodeID      uint64  // ノードID (10ビット)
           sequence    uint64  // シーケンス番号 (12ビット)
           lastTime    uint64  // 最後に生成した時刻
       }
       
       func NewSnowflakeIDGenerator(nodeID uint64) *SnowflakeIDGenerator {
           // 2020年1月1日をカスタムエポックとする
           epoch := uint64(time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC).UnixMilli())
           return &SnowflakeIDGenerator{
               epoch:  epoch,
               nodeID: nodeID & 0x3FF, // 10ビットに制限
           }
       }
       
       func (g *SnowflakeIDGenerator) Generate() (uint64, error) {
           g.mutex.Lock()
           defer g.mutex.Unlock()
           
           now := uint64(time.Now().UnixMilli())
           
           if now < g.lastTime {
               return 0, fmt.Errorf("clock moved backwards")
           }
           
           if now == g.lastTime {
               g.sequence = (g.sequence + 1) & 0xFFF // 12ビットに制限
               if g.sequence == 0 {
                   // シーケンスがオーバーフローした場合、次のミリ秒まで待機
                   for now <= g.lastTime {
                       now = uint64(time.Now().UnixMilli())
                   }
               }
           } else {
               g.sequence = 0
           }
           
           g.lastTime = now
           
           // ID構成: 1ビット(予約) + 41ビット(時刻) + 10ビット(ノードID) + 12ビット(シーケンス)
           id := ((now - g.epoch) << 22) | (g.nodeID << 12) | g.sequence
           return id, nil
       }
       
       func (g *SnowflakeIDGenerator) ParseID(id uint64) (timestamp time.Time, nodeID uint64, sequence uint64) {
           ms := (id >> 22) + g.epoch
           timestamp = time.UnixMilli(int64(ms))
           nodeID = (id >> 12) & 0x3FF
           sequence = id & 0xFFF
           return
       }
    
  4. 大容量データ処理とカウンター
       type DataProcessor struct {
           RecordsProcessed uint64
           BytesProcessed   uint64
           ErrorCount       uint64
           StartTime        uint64
       }
       
       func NewDataProcessor() *DataProcessor {
           return &DataProcessor{
               StartTime: uint64(time.Now().UnixNano()),
           }
       }
       
       func (dp *DataProcessor) ProcessRecord(data []byte) error {
           // データ処理のシミュレーション
           if len(data) == 0 {
               dp.ErrorCount++
               return fmt.Errorf("empty data")
           }
           
           dp.RecordsProcessed++
           dp.BytesProcessed += uint64(len(data))
           return nil
       }
       
       func (dp *DataProcessor) GetStatistics() map[string]interface{} {
           currentTime := uint64(time.Now().UnixNano())
           elapsedNanos := currentTime - dp.StartTime
           elapsedSeconds := float64(elapsedNanos) / float64(time.Second)
           
           recordsPerSecond := float64(dp.RecordsProcessed) / elapsedSeconds
           bytesPerSecond := float64(dp.BytesProcessed) / elapsedSeconds
           
           return map[string]interface{}{
               "records_processed": dp.RecordsProcessed,
               "bytes_processed":   FormatBytes(dp.BytesProcessed),
               "error_count":       dp.ErrorCount,
               "elapsed_seconds":   elapsedSeconds,
               "records_per_sec":   recordsPerSecond,
               "bytes_per_sec":     FormatBytes(uint64(bytesPerSecond)),
               "error_rate":        float64(dp.ErrorCount) / float64(dp.RecordsProcessed),
           }
       }
    
  5. ハッシュ値と暗号学的処理
       import (
           "crypto/sha256"
           "encoding/binary"
           "hash/fnv"
       )
       
       func Hash64FNV(data []byte) uint64 {
           h := fnv.New64a()
           h.Write(data)
           return h.Sum64()
       }
       
       func Hash64SHA256(data []byte) uint64 {
           hash := sha256.Sum256(data)
           // SHA256の最初の8バイトを取得
           return binary.BigEndian.Uint64(hash[:8])
       }
       
       type BloomFilter struct {
           bitArray []bool
           size     uint64
           hashFuncs []func([]byte) uint64
       }
       
       func NewBloomFilter(size uint64, hashCount int) *BloomFilter {
           return &BloomFilter{
               bitArray: make([]bool, size),
               size:     size,
               hashFuncs: []func([]byte) uint64{
                   Hash64FNV,
                   Hash64SHA256,
               },
           }
       }
       
       func (bf *BloomFilter) Add(data []byte) {
           for _, hashFunc := range bf.hashFuncs {
               index := hashFunc(data) % bf.size
               bf.bitArray[index] = true
           }
       }
       
       func (bf *BloomFilter) MightContain(data []byte) bool {
           for _, hashFunc := range bf.hashFuncs {
               index := hashFunc(data) % bf.size
               if !bf.bitArray[index] {
                   return false
               }
           }
           return true
       }
    
  6. ネットワーク統計とトラフィック監視
       type NetworkInterface struct {
           Name         string
           BytesSent    uint64
           BytesRecv    uint64
           PacketsSent  uint64
           PacketsRecv  uint64
           ErrorsSent   uint64
           ErrorsRecv   uint64
           LastUpdated  uint64
       }
       
       type TrafficMonitor struct {
           interfaces map[string]*NetworkInterface
           startTime  uint64
       }
       
       func NewTrafficMonitor() *TrafficMonitor {
           return &TrafficMonitor{
               interfaces: make(map[string]*NetworkInterface),
               startTime:  uint64(time.Now().UnixNano()),
           }
       }
       
       func (tm *TrafficMonitor) UpdateInterface(name string, bytesSent, bytesRecv, packetsSent, packetsRecv uint64) {
           iface, exists := tm.interfaces[name]
           if !exists {
               iface = &NetworkInterface{Name: name}
               tm.interfaces[name] = iface
           }
           
           iface.BytesSent = bytesSent
           iface.BytesRecv = bytesRecv
           iface.PacketsSent = packetsSent
           iface.PacketsRecv = packetsRecv
           iface.LastUpdated = uint64(time.Now().UnixNano())
       }
       
       func (tm *TrafficMonitor) GetTotalTraffic() (uint64, uint64) {
           var totalSent, totalRecv uint64
           for _, iface := range tm.interfaces {
               totalSent += iface.BytesSent
               totalRecv += iface.BytesRecv
           }
           return totalSent, totalRecv
       }
       
       func (tm *TrafficMonitor) GetBandwidthUsage(interfaceName string) (float64, float64) {
           iface, exists := tm.interfaces[interfaceName]
           if !exists {
               return 0, 0
           }
           
           elapsedNanos := uint64(time.Now().UnixNano()) - tm.startTime
           elapsedSeconds := float64(elapsedNanos) / float64(time.Second)
           
           sentPerSecond := float64(iface.BytesSent) / elapsedSeconds
           recvPerSecond := float64(iface.BytesRecv) / elapsedSeconds
           
           return sentPerSecond, recvPerSecond
       }
    
  7. データベース/キーバリューストア
       type KeyValueStore struct {
           data        map[uint64][]byte
           nextKey     uint64
           totalSize   uint64
           maxSize     uint64
           accessCount uint64
       }
       
       func NewKeyValueStore(maxSize uint64) *KeyValueStore {
           return &KeyValueStore{
               data:    make(map[uint64][]byte),
               nextKey: 1,
               maxSize: maxSize,
           }
       }
       
       func (kvs *KeyValueStore) Put(value []byte) (uint64, error) {
           valueSize := uint64(len(value))
           if kvs.totalSize+valueSize > kvs.maxSize {
               return 0, fmt.Errorf("insufficient space")
           }
           
           key := kvs.nextKey
           kvs.data[key] = make([]byte, len(value))
           copy(kvs.data[key], value)
           kvs.totalSize += valueSize
           kvs.nextKey++
           
           return key, nil
       }
       
       func (kvs *KeyValueStore) Get(key uint64) ([]byte, error) {
           kvs.accessCount++
           value, exists := kvs.data[key]
           if !exists {
               return nil, fmt.Errorf("key not found")
           }
           
           result := make([]byte, len(value))
           copy(result, value)
           return result, nil
       }
       
       func (kvs *KeyValueStore) Delete(key uint64) error {
           value, exists := kvs.data[key]
           if !exists {
               return fmt.Errorf("key not found")
           }
           
           kvs.totalSize -= uint64(len(value))
           delete(kvs.data, key)
           return nil
       }
       
       func (kvs *KeyValueStore) GetStats() map[string]uint64 {
           return map[string]uint64{
               "total_keys":    uint64(len(kvs.data)),
               "total_size":    kvs.totalSize,
               "max_size":      kvs.maxSize,
               "access_count":  kvs.accessCount,
               "next_key":      kvs.nextKey,
           }
       }
    
  8. バイナリファイル処理とシリアライゼーション
       import (
           "encoding/binary"
           "io"
       )
       
       type LargeFileHeader struct {
           Magic        uint64
           Version      uint64
           FileSize     uint64
           RecordCount  uint64
           Timestamp    uint64
           Checksum     uint64
       }
       
       func (h LargeFileHeader) WriteTo(w io.Writer) error {
           return binary.Write(w, binary.LittleEndian, h)
       }
       
       func ReadLargeFileHeader(r io.Reader) (LargeFileHeader, error) {
           var header LargeFileHeader
           err := binary.Read(r, binary.LittleEndian, &header)
           return header, err
       }
       
       type LargeFileReader struct {
           file        io.ReadSeeker
           header      LargeFileHeader
           currentPos  uint64
           recordSize  uint64
       }
       
       func NewLargeFileReader(file io.ReadSeeker, recordSize uint64) (*LargeFileReader, error) {
           header, err := ReadLargeFileHeader(file)
           if err != nil {
               return nil, err
           }
           
           return &LargeFileReader{
               file:       file,
               header:     header,
               currentPos: 0,
               recordSize: recordSize,
           }, nil
       }
       
       func (lfr *LargeFileReader) ReadRecord(index uint64) ([]byte, error) {
           if index >= lfr.header.RecordCount {
               return nil, fmt.Errorf("index out of range")
           }
           
           offset := int64(binary.Size(lfr.header)) + int64(index*lfr.recordSize)
           _, err := lfr.file.Seek(offset, io.SeekStart)
           if err != nil {
               return nil, err
           }
           
           record := make([]byte, lfr.recordSize)
           _, err = io.ReadFull(lfr.file, record)
           if err != nil {
               return nil, err
           }
           
           return record, nil
       }
       
       func (lfr *LargeFileReader) GetRecordCount() uint64 {
           return lfr.header.RecordCount
       }
    

注意点

  1. オーバーフロー: 最大値(18446744073709551615)を超えると、0に戻ります
       var x uint64 = 18446744073709551615
       x++ // x は 0 になる
       
       // オーバーフロー対策
       func safeAdd64(a, b uint64) (uint64, bool) {
           if a > 18446744073709551615-b {
               return 0, false // オーバーフロー
           }
           return a + b, true
       }
       
       // 大きな数値の安全な演算
       func safeMul64(a, b uint64) (uint64, bool) {
           if a == 0 || b == 0 {
               return 0, true
           }
           if a > 18446744073709551615/b {
               return 0, false // オーバーフロー
           }
           return a * b, true
       }
    
  2. パフォーマンスの考慮: 32ビットシステムでは64ビット演算が遅い場合があります
       import "runtime"
       
       func chooseIDType() {
           if runtime.GOARCH == "386" || runtime.GOARCH == "arm" {
               // 32ビットシステムではuint32の使用を検討
               fmt.Println("32-bit system detected, consider using uint32 for better performance")
           }
       }
    
  3. JSON/XMLシリアライゼーション: JavaScriptの数値精度の制限に注意
       import (
           "encoding/json"
           "strconv"
       )
       
       type BigNumber struct {
           Value uint64
       }
       
       // カスタムJSON marshaling
       func (bn BigNumber) MarshalJSON() ([]byte, error) {
           // JavaScriptの安全な整数範囲を超える場合は文字列として送信
           if bn.Value > 9007199254740991 { // 2^53 - 1
               return json.Marshal(strconv.FormatUint(bn.Value, 10))
           }
           return json.Marshal(bn.Value)
       }
       
       func (bn *BigNumber) UnmarshalJSON(data []byte) error {
           var str string
           if err := json.Unmarshal(data, &str); err == nil {
               value, err := strconv.ParseUint(str, 10, 64)
               if err != nil {
                   return err
               }
               bn.Value = value
               return nil
           }
           
           return json.Unmarshal(data, &bn.Value)
       }
    
  4. atomic操作: 並行アクセス時は原子的操作を使用
       import "sync/atomic"
       
       type AtomicCounter struct {
           value uint64
       }
       
       func (ac *AtomicCounter) Increment() uint64 {
           return atomic.AddUint64(&ac.value, 1)
       }
       
       func (ac *AtomicCounter) Get() uint64 {
           return atomic.LoadUint64(&ac.value)
       }
       
       func (ac *AtomicCounter) Set(value uint64) {
           atomic.StoreUint64(&ac.value, value)
       }
       
       func (ac *AtomicCounter) CompareAndSwap(old, new uint64) bool {
           return atomic.CompareAndSwapUint64(&ac.value, old, new)
       }
    
  5. 時間精度: ナノ秒精度を活用する際の注意点
       func measureHighPrecision(fn func()) time.Duration {
           start := time.Now()
           fn()
           end := time.Now()
           
           // ナノ秒精度での測定
           return end.Sub(start)
       }
       
       // システムクロックの精度確認
       func checkClockResolution() {
           var prev uint64
           var count int
           start := time.Now()
           
           for time.Since(start) < time.Millisecond {
               current := uint64(time.Now().UnixNano())
               if current != prev {
                   count++
                   prev = current
               }
           }
           
           fmt.Printf("Clock resolution: approximately %d nanoseconds\n", 
               int(time.Millisecond.Nanoseconds())/count)
       }
    

uint64型は、大容量データ処理、高精度タイミング、一意ID生成、ネットワーク統計など、非常に大きな数値を扱う場面で威力を発揮します。ただし、オーバーフローやパフォーマンス、プラットフォーム間の互換性には十分注意して使用することが重要です。

カテゴリ:Go
カテゴリ:Go