ホームページ >バックエンド開発 >Golang >unsafe.Pointer から Go スライスまたは配列を効率的に作成する方法

unsafe.Pointer から Go スライスまたは配列を効率的に作成する方法

DDD
DDDオリジナル
2024-12-06 05:04:13451ブラウズ

How to Efficiently Create Go Slices or Arrays from unsafe.Pointer?

Golang で unsafe.Pointer からスライスまたは配列を作成する: 効率的な代替手段

配列へのポインタは、Golang では uintptr 値として表すことができます。ただし、ポインタが uintptr として格納されている場合、元の配列にアクセスするのは困難になる可能性があります。

非効率な方法: メモリのコピー

1 つの単純なアプローチは、データをコピーすることです。新しいスライスへのポインタ:

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

より効率的な方法は、reflect.SliceHeader を使用してスライスを作成することです。またはメモリをコピーせずに配列:

var data []byte

sh := (*reflect.SliceHeader)(unsafe.Pointer(&data))
sh.Data = p
sh.Len = size
sh.Cap = size

fmt.Println(data)

このメソッドは uintptr を.SliceHeader を反映し、そのフィールドが既存の配列を指すように変更されます。結果のスライスまたは配列は、元の配列と同じ基礎となるメモリを共有します。

代替方法: 複合リテラル

もう 1 つの代替方法は、複合リテラルを使用して、 reflect.SliceHeader:

sh := &reflect.SliceHeader{
    Data: p,
    Len:  size,
    Cap:  size,
}

data := *(*[]byte)(unsafe.Pointer(sh))

fmt.Println(data)

このアプローチでは、前のアプローチと同じ結果が生成されます。 method.

注意事項

uintptr ポインターを使用する場合は、ポインターの存続期間中、元の配列が有効であることを確認することが重要です。さらに、パッケージアンセーフはタイプセーフティに影響を与える可能性があるため、慎重に使用する必要があります。

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

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。