2016-06-23 9 views
0

のバイト数をカウントするために、私は次の変数を持っている:どのように整数

var foo int8 
var bar [5]int8 

私は、変数と出力の両方に合計をバイト数をカウントしたい - そう右ここでは1 + 5 = 6する必要があります。これは可能ですか?

答えて

2

あなたはreflect.Sizeを使用することができ、これはいくつかの理由でuintptrを返しますが、unsafeを使用せずに、実際にunsafe.SizeOfとしてだけでまったく同じことです。

var x [8]byte 

t := reflect.TypeOf(x) 

fmt.Println(t.Size()) 

思わぬ障害は、あなたが、ヘッダ/メタデータ(またはポインタのためだけに、ポインタのサイズ)の大きさを得るでしょうこれ、マップ、スライス、文字列、およびポインタであることを行っています。それが大丈夫なら大丈夫です!そうでない場合、あなたはさまざまな方法でこれを処理することができ、これは私が私の頭の上から持っている最高です:

func UnderlyingSize(x interface{}) uintptr { 
    v := reflect.ValueOf(x) 
    t := v.Type() 

    var size uintptr; 

    switch t.Kind() { 
    // For the builtin collections, we just multiply the len by the 
    // element size, for maps also do the key 
    case reflect.Map: 
     l := uintptr(v.Len()) 
     size = t.Key().Size()*l + t.Elem().Size()*l 
    case reflect.Slice: 
     t := t.Elem(); 
     size = t.Size() * uintptr(v.Len()) 
    case reflect.Ptr: 
     t := t.Elem(); 
     size = t.Size() 
    // Strings are just byte arrays, so it's just the len 
    case reflect.String: 
     size = uintptr(v.Len()) 
    // For an interface, we need to find the underlying type 
    case reflect.Interface: 
     v := v.Elem() 
     size = UnderlyingSize(v) 
    // For anything else, including arrays, Size returns the correct value 
    default: 
     size = t.Size(); 
    } 

    return size 
} 

ありLenではなくCapを使用するために作られている引数があるが、それはに十分に簡単ですあなた自身を変えなさい。ヘッダー情報のサイズと基本サイズが必要な場合は、t.Size()をこれらの値のいずれかに追加することもできます。実際のmapは恐らくキー+値+ヘッダーサイズよりも多くのメモリを必要とすると警告していることに注意してください。

コレクションのデータ構造がある場合は、このようなものを自分で実装する必要がありますが、シンプルな構造体(つまり、POD構造体と組み込み型のみ)の場合は、UnderlyingSizeをすべてのメンバー。

関連する問題