二つの方法でポインタを移動し、一方がUIntPtr内蔵型、本質的に整数であり、他方は任意の型を指すことができるポインタを示すポインタ危険パケットが設けられています。Uintptrは、典型的には、それが整数であるため、ポインタを計算するために使用される、次へのポインタ点の位置を計算することは容易であり、そしてunsafe.Pointerはポインタの異なる種類の、各変換を架橋するために使用されます。
また、ゴーunsafe.Pointerと使用uintptrいくつかのガイドラインを提供します。
これらの基本的な概念では、どのように我々は遊ぶことができますか?
通常、我々はそうすることの文字列に変換される] [バイトになります。
b := byte[]("Peppa")
string(b)
この方法では、元のメモリ内の任意のメモリ、型変換を割り当てるべきではない、より効率的な方法をメモリを割り当て、コピーする問題があります。
元の配列とlenを指し示すポインタを含んでいるスライス構造は、本質的に、キャップ部材は、スライスを介してパッケージが表される反映さ見ることができます。
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
元の配列の最初の要素へのポインタであるデータ。メモリは、より多くの構造やスライスのようなものですので、バイトのスライスが文字列に元の文字列に変換することができる理由、反映パッケージが表され、この文字列を通して見ることができます。
type StringHeader struct {
Data uintptr
Len int
}
だから私たちはただ、元のメモリにそれにStringHeaderを構築しました。
sh := reflect.StringHeader{
uintptr(unsafe.Pointer(&b[0])),
len(b),
}
スライスのスライス、レン長の最初の要素であるデータポイント。本明細書で使用されるようunsafe.Pointerがブリッジされて。
StringHeaderオブジェクトを作成し、次のステップは、文字列型のオブジェクトに変換することで、どのようにそれを行うには?またはunsafe.Pointerによってブリッジ。
*(*string)(unsafe.Pointer(&sh))
StringHeader第型unsafe.Pointer変換へのポインタ、およびその後unsafe.Pointerストリングポインタタイプ、最終的に実際のポインタ値により得られる値に変換されます。
このタイプの変換は、与えられた例は、数学パッケージFloat64bits方法であり、また、記載危険なパッケージで方法unsafe.Pointerによるものです。
func Float64bits(f float64) uint64 {
return *(*uint64)(unsafe.Pointer(&f))
}
我々は2つの方法がメモリを再割り当てするかどうかを確認することができます。
import (
"github.com/davecgh/go-spew/spew"
"unsafe"
"reflect"
"fmt"
)
func byteToString(b []byte) string {
return string(b)
}
func byteToStringNoAlloc(b []byte) string {
if len(v) == 0 {return ""}
sh := reflect.StringHeader{uintptr(unsafe.Pointer(&b[0])), len(b)}
return *(*string)(unsafe.Pointer(&sh))
}
func main() {
b := []byte("Peppa")
fmt.Println("切片第一个元素: ", spew.Sdump(&b[0]))
str := byteToString(b)
sh := (*reflect.StringHeader)(unsafe.Pointer(&str))
fmt.Println("分配内存的方式: ", spew.Sdump(sh))
strNoAlloc := byteToStringNoAlloc(b)
shNoAlloc := (*reflect.StringHeader)(unsafe.Pointer(&toStr))
fmt.Println("不分配内存的方式: ", spew.Sdump(shNoAlloc))
}
これはuintptrは安全でないため、いつでも再利用することができるので、メモリの一部が回収されたときに、元のメモリ上で動作するように変換することができるメモリで、より深刻な問題へのデータの上昇を与えます警戒するので、この方法では、パニックにつながります。
危険なパッケージには、安全なstringHeaderとsliceHeaderを提供しますが、それらが公開されないので、キャストをリサイクルされていないメモリを回避するための方法がありませんでした。