The Go Programming Language Specificationの翻訳、最終回です。
すべての訳はGo言語仕様[日本語訳]にまとめてあります。
システム考察
unsafeパッケージ
組み込みパッケージunsafeは、コンパイラに実装されており、低レベルのプログラミング向けの機能を提供します。これには型システムから逸脱した機能が含まれています。そのためunsafeを使っているパッケージは、型が安全であることを手作業でよく確認しておかなくてはなりません。このパッケージでは、以下のインタフェースを提供しています。
package unsafe
type ArbitraryType int // shorthand for an arbitrary Go type; it is not a real type
type Pointer *ArbitraryType
func Alignof(variable ArbitraryType) int
func Offsetof(selector ArbitraryType) int
func Sizeof(variable ArbitraryType) int
func Reflect(val interface {}) (typ runtime.Type, addr uintptr)
func Typeof(val interface {}) reflect.Type
func Unreflect(typ runtime.Type, addr uintptr) interface{}
すべてのポインタ、およびuintptr型の値は、Pointerに変換することができます。またその逆も可能です。
Sizeof関数は、変数を表す式を受け取り、その変数のサイズをバイト数で返します。
Offsetof関数は、構造体のフィールド表すセレクタ(§セレクタ)を受け取り、構造体のアドレスからフィールドへの相対オフセットをバイト数で返します。下は構造体sのフィールドfを使った例です。
uintptr(unsafe.Pointer(&s)) + uintptr(unsafe.Offsetof(s.f)) == uintptr(unsafe.Pointer(&s.f))
コンピュータのアーキテクチャによっては、メモリのアドレスにアライメントが必要となることがあるため、変数のアドレスは、変数の型が持つアライメントも考慮します。Alignof関数は、変数を表す式を受け取り、変数(の型)のアライメントをバイト数で返します。下は変数xを使った例です。
uintptr(unsafe.Pointer(&x)) % uintptr(unsafe.Alignof(x)) == 0
Alignof、Offsetof、Sizeofの呼び出しは、コンパイル時にint型の定数となります。
unsafe.Typeof、unsafe.Reflect、unsafe.Unreflect関数は、実行時にインタフェースに格納されている動的な型および値へのアクセスを許します。Typeofは、valの動的な型を runtime.Typeとして返します。Reflectは、valの動的な値のコピーを割り当て、型とそのコピーのアドレスを返します。UnreflectはReflectの逆で、型とアドレスからインタフェースの値を作成します。これらの関数を利用しているreflectパッケージでは、インタフェースの値を安全、かつより便利に調べる方法を提供しています。
サイズとアライメントの保証
数値型(§数値型)では、以下に示すサイズが保証されています。
型 サイズ(バイト数) byte, uint8, int8 1 uint16, int16 2 uint32, int32, float32 4 uint64, int64, float64 8
以下に示す、アライメントの特性が最低限保証されています。
- 変数
x(型は問わない):1 <= unsafe.Alignof(x) <= unsafe.Maxalign - 変数
xが数値型のとき:unsafe.Alignof(x)は、unsafe.Sizeof(x)およびunsafe.Maxalign以下であり、少なくとも1以上である。 - 変数
xが構造体型のとき:unsafe.Alignof(x)は、xの各フィールドをfとしたときunsafe.Alignof(x.f)の中で一番大きい値と同じであり、少なくとも1以上である。 - 変数
xが配列型のとき:unsafe.Alignof(x)は、unsafe.Alignof(x[0])と同じであり、少なくとも1以上である。
実装との差異 – TODO
- 実装は、gotoステートメント、および(宣言以外の)宛先に対する制約を守っていません。
- メソッド式は未実装です。
- Gccgoではひとつのソースファイルに、ひとつのinit()関数しか許していません。
Trackback URL
Leave a comment
Comments