システムに関する考慮事項
unsafe
パッケージ
組み込みパッケージ unsafe
はコンパイラに認識され、インポートパス "unsafe"
を通じてアクセス可能です。このパッケージは型システムに違反する操作を含む低レベルプログラミング機能を提供します。unsafe
パッケージを使用するパッケージは、型安全性を手動で検証する必要があり、移植性が保証されない場合があります。パッケージは以下のインターフェイスを提供します:
package unsafe
type ArbitraryType int // 任意のGo型を表す省略形;実際の型ではない
type Pointer *ArbitraryType
func Alignof(variable ArbitraryType) uintptr
func Offsetof(selector ArbitraryType) uintptr
func Sizeof(variable ArbitraryType) uintptr
type IntegerType int // 整数型を表す省略形;実際の型ではない
func Add(ptr Pointer, len IntegerType) Pointer
func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType
func SliceData(slice []ArbitraryType) *ArbitraryType
func String(ptr *byte, len IntegerType) string
func StringData(str string) *byte
Pointer
はポインタ型ですが、Pointer
値は参照解除できません。基底型が uintptr
であるポインタまたは値は、基底型が Pointer
である型に変換でき、その逆も可能です。それぞれの型が型パラメータである場合、それぞれの型セット内のすべての型は同じ基底型を持つ必要があり、それぞれ uintptr
と Pointer
でなければなりません。Pointer
と uintptr
間の変換の効果は実装定義です。
var f float64
bits = *(*uint64)(unsafe.Pointer(&f))
type ptr unsafe.Pointer
bits = *(*uint64)(ptr(&f))
func f[P ~*B, B any](p P) uintptr {
return uintptr(unsafe.Pointer(p))
}
var p ptr = nil
関数 Alignof
と Sizeof
は任意の型の式 x
を取り、あたかも var v = x
を通じて変数 v
が宣言されたかのように、仮想的な変数 v
のアラインメントまたはサイズをそれぞれ返します。
関数 Offsetof
は(場合によっては括弧で囲まれた)セレクタ s.f
を取ります。これは s
または *s
で示される構造体のフィールド f
を示し、構造体のアドレスを基準としたフィールドのオフセットをバイト単位で返します。f
が埋め込まれたフィールドの場合、構造体のフィールドを通じてポインタによる間接参照なしで到達可能でなければなりません。フィールド f
を持つ構造体 s
の場合:
uintptr(unsafe.Pointer(&s)) + unsafe.Offsetof(s.f) == uintptr(unsafe.Pointer(&s.f))
コンピュータアーキテクチャでは、メモリアドレスがアラインメントされていることが要求される場合があります。つまり、変数のアドレスが変数の型のアラインメントという要素の倍数であることが求められます。関数 Alignof
は任意の型の変数を示す式を取り、バイト単位で変数(の型)のアラインメントを返します。変数 x
の場合:
uintptr(unsafe.Pointer(&x)) % unsafe.Alignof(x) == 0
型 T
の(変数)は、T
が型パラメータである場合、または可変サイズの要素やフィールドを含む配列または構造体型である場合に可変サイズを持ちます。それ以外の場合、サイズは定数です。Alignof
、Offsetof
、Sizeof
の呼び出しは、引数(または Offsetof
のセレクタ式 s.f
における構造体 s
)が定数サイズの型である場合、型 uintptr
の定数式です。
関数 Add
は ptr
に len
を加算し、更新されたポインタ unsafe.Pointer(uintptr(ptr) + uintptr(len))
を返しますGo 1.17。len
引数は整数型または型なしの定数である必要があります。定数 len
引数は型 int
の値で表現可能でなければなりません;型なしの定数の場合は型 int
が与えられます。Pointer
の有効な使用に関するルールは引き続き適用されます。
関数 Slice
は、基礎となる配列が ptr
から始まり、長さと容量が len
であるスライスを返します。Slice(ptr, len)
は以下と同等です:
(*[len]ArbitraryType)(unsafe.Pointer(ptr))[:]
ただし、特殊なケースとして、ptr
が nil
で len
がゼロの場合、Slice
は nil
を返します Go 1.17。
len
引数は整数型または型なしの定数である必要があります。定数 len
引数は非負数で、型 int
の値で表現可能でなければなりません;型なしの定数の場合は型 int
が与えられます。実行時に、len
が負の場合、または ptr
が nil
で len
がゼロでない場合、実行時パニックが発生します Go 1.17。
関数 SliceData
は slice
引数の基礎となる配列へのポインタを返します。スライスの容量 cap(slice)
がゼロでない場合、そのポインタは &slice[:1][0]
です。slice
が nil
の場合、結果は nil
です。それ以外の場合は、未指定のメモリアドレスへの非 nil
ポインタです Go 1.20。
関数 String
は、基礎となるバイトが ptr
から始まり、長さが len
である string
値を返します。ptr
と len
の引数には、関数 Slice
と同じ要件が適用されます。len
がゼロの場合、結果は空の文字列 ""
です。Go の文字列は不変であるため、String
に渡されるバイトはその後変更してはいけません Go 1.20。
関数 StringData
は str
引数の基礎となるバイトへのポインタを返します。空の文字列の場合、戻り値は未指定であり、nil
かもしれません。Go の文字列は不変であるため、StringData
によって返されるバイトは変更してはいけません Go 1.20。
サイズとアラインメントの保証
数値型については、以下のサイズが保証されています:
型 サイズ(バイト)
byte, uint8, int8 1
uint16, int16 2
uint32, int32, float32 4
uint64, int64, float64, complex64 8
complex128 16
以下の最小アラインメント特性が保証されています:
任意の型の変数
x
について:unsafe.Alignof(x)
は少なくとも 1 です。構造体型の変数
x
について:unsafe.Alignof(x)
は、x
の各フィールドf
に対するunsafe.Alignof(x.f)
の値のうち最大のものですが、少なくとも 1 です。配列型の変数
x
について:unsafe.Alignof(x)
は配列の要素型の変数のアラインメントと同じです。
構造体または配列型は、サイズがゼロより大きいフィールド(または要素)を含まない場合、サイズがゼロになります。2つの異なるゼロサイズの変数は、メモリ内で同じアドレスを持つことがあります。