関連記事
GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ
概要
以下、自分用のメモです。
unsafeパッケージって、Goの安全性の枠から外れる操作をするパッケージなので、基本的に使わないほうが良いものですが、知ってると便利なパッケージでもあります。
cgoを使う場合はほぼ必須です。特に unsafe.Pointer はめっちゃ使います。
unsafe.Pointer は、C言語でいう (void *) と同じものとなるので、これを利用することで任意の型にキャストできます。
unsafe.Pointer については、以前の記事でサンプル作ったので、そちらご参照ください。
今回は、*byteと[]byteの相互変換について。主に低レベルなAPI操作やcgoなどで利用したりします。
unsafe.SliceData は、特定のスライス []T を *T に変換してくれます。これはGoのヒープメモリを指すポインタとなります。
unsafe.Slice は、逆を行うものです。つまり、*T を []T にしてくれる関数。ポインタとサイズを渡すとスライスにして返してくれます。
こちらは元のデータが指すポインタをそのまま指した状態で返してくれます。つまり、C側のポインタを渡してスライスにした場合はC側のスタックメモリをそのまま指している状態となります。
元のデータのポインタを直接指しているので、C側から受け取った char * なんかを unsafe.Slice を使ってスライスにして、それを変更などするとC側のスタックメモリを直接変更することになります。非常に危険です。データを見る分には問題ありません。
今回は、使い方だけサンプルとして。実際にcgoを使ってやり取りするサンプルは次回。
サンプル
package unsafes import ( "bytes" "fmt" "unsafe" ) // Slice は、unsafe.SliceData() と unsafe.Slice() のサンプルです。 // // unsafe.SliceData() は、特定のスライスを *T に変換する関数。 // 逆を行ってくれるのが unsafe.Slice() となる。 // // REFERENCES: // - https://pkg.go.dev/unsafe@go1.25.3#SliceData func Slice() error { var ( original = []byte("helloworld") result []byte ptr *byte ) ptr = unsafe.SliceData(original) // []byteを*byteに変換 result = unsafe.Slice(ptr, len(original)) // *byteを[]byteに変換 fmt.Printf("b1 equals b2: %v\n", bytes.Equal(original, result)) return nil }
実行
$ task task: [build] go build -o "/home/dev/dev/try-golang/try-golang" . task: [run] ./try-golang -onetime ENTER EXAMPLE NAME: unsafe_slice [Name] "unsafe_slice" b1 equals b2: true [Elapsed] 15.886µs
参考情報
個人的Goのおすすめ書籍
個人的に読んでとても勉強になった書籍さんたちです。
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。






