ホームページ > バックエンド開発 > Golang > unsafe.Pointer から Go 配列またはスライスを効率的に作成するにはどうすればよいですか?

unsafe.Pointer から Go 配列またはスライスを効率的に作成するにはどうすればよいですか?

Barbara Streisand
リリース: 2024-12-11 02:25:16
オリジナル
698 人が閲覧しました

How to Efficiently Create a Go Array or Slice from an unsafe.Pointer?

安全でない配列から配列またはスライスを効率的に初期化する方法。Go のポインター

Go の世界では、シナリオに遭遇する可能性があります。ここでは、unsafe.Pointer として表されるデータ構造を操作する必要があります。たとえば、

p := uintptr(unsafe.Pointer(&array))
size := 5
ログイン後にコピー

のような配列へのポインターがあるとします。ただし、ポインターは単にそのアドレスを表すものであるため、配列に直接アクセスすることは不可能です。このため、メモリ コピーに頼ることなく、既知のポインタ、サイズ、データ型を使用して配列またはスライスを作成するという課題が残ります。

配列/スライス作成に対する安全でないアプローチ

最初に、次のアプローチを検討できます:

data := make([]byte, size)
stepSize := unsafe.Sizeof(data[0])
for i := 0; i < size; i++ {
    data[i] = *(*byte)(unsafe.Pointer(p))
    p += stepSize
}
ログイン後にコピー

この解決策は、元の配列から新しいスライスにデータをコピーします。これは、特に大規模なデータセットの場合、非効率的になる可能性があります。

reflect.SliceHeader を使用した効率的なアプローチ

より効率的な代替方法は、Go のリフレクション パッケージと反映.SliceHeader タイプ。 Reflect.SliceHeader のフィールドを直接操作することで、ポインタと同じ基になるデータを参照する配列またはスライスを作成できます。

ステップ 1:reflect.SliceHeader 記述子を取得する

スライス変数を宣言し、unsafe を使用してその []byte 型を *reflect.SliceHeader にキャストします変換:

var data []byte
sh := (*reflect.SliceHeader)(unsafe.Pointer(&data))
ログイン後にコピー

ステップ 2: SliceHeader フィールドを変更する

reflect.SliceHeader:

sh.Data = p
sh.Len = size
sh.Cap = size
ログイン後にコピー

ステップ 3: 元のデータに変換し直すtype

最後に、安全でない変換を使用して、変更したreflect.SliceHeaderを目的のデータ型にキャストして戻します:

data = *(*[]byte)(unsafe.Pointer(sh))
ログイン後にコピー
この効率的なアプローチにより、共有する配列またはスライスを作成できます。不必要なメモリコピーのコストを発生させることなく、ポインタと同じ基礎となるデータを取得できます。

以上がunsafe.Pointer から Go 配列またはスライスを効率的に作成するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート