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

AlignofOffsetofSizeofの呼び出しは、コンパイル時にint型の定数となります。

unsafe.Typeofunsafe.Reflectunsafe.Unreflect関数は、実行時にインタフェースに格納されている動的な型および値へのアクセスを許します。Typeofは、valの動的な型を runtime.Typeとして返します。Reflectは、valの動的な値のコピーを割り当て、型とそのコピーのアドレスを返します。UnreflectReflectの逆で、型とアドレスからインタフェースの値を作成します。これらの関数を利用しているreflectパッケージでは、インタフェースの値を安全、かつより便利に調べる方法を提供しています。

サイズとアライメントの保証

数値型(§数値型)では、以下に示すサイズが保証されています。

型                        サイズ(バイト数)

byte, uint8, int8         1
uint16, int16             2
uint32, int32, float32    4
uint64, int64, float64    8

以下に示す、アライメントの特性が最低限保証されています。

  1. 変数x(型は問わない):1 <= unsafe.Alignof(x) <= unsafe.Maxalign
  2. 変数xが数値型のとき:unsafe.Alignof(x)は、 unsafe.Sizeof(x)およびunsafe.Maxalign 以下であり、少なくとも1以上である。
  3. 変数xが構造体型のとき:unsafe.Alignof(x)は、xの各フィールドをfとしたときunsafe.Alignof(x.f)の中で一番大きい値と同じであり、少なくとも1以上である。
  4. 変数xが配列型のとき:unsafe.Alignof(x)は、unsafe.Alignof(x[0])と同じであり、少なくとも1以上である。

実装との差異 – TODO

  • 実装は、gotoステートメント、および(宣言以外の)宛先に対する制約を守っていません。
  • メソッド式は未実装です。
  • Gccgoではひとつのソースファイルに、ひとつのinit()関数しか許していません。