今日は一日ですが週末です。 Go1.17 に関するちょっとしたニュースを共有させてください。毎日集魚スキルを身につけよう!
Go 言語では、スライスには、その配列が独立変数としてどこかに存在するか、スライスをサポートするために割り当てられた単なる配列であるかに関係なく、サポートする配列への参照が含まれます。
スライスの基本構造は次のとおりです。
// runtime/slice.go type slice struct { array unsafe.Pointer // 指向底层数组的指针 len int // 长度 cap int // 容量 }
配列をサポートする現在のスライス方法では、スライス中に興味深いメモリ リークが発生したり、スライスに驚くべき変更が発生したりする可能性があります。
もう 1 つの非常に重要な点は、Go 1.16 以前では、スライス型から配列型に変換する安全な方法がなく、非常に無力であるということです。
標準ライブラリのreflectまたはunsafeを呼び出して、安全でないコードを記述することによってのみこれを行うことができます:
(*[10]byte)(unsafe.Pointer(&b[0]))
これは明らかにエレガントではなく、公式自体も、処理が完了したら、 unsafe を使用することを推奨していません。問題が発生すると、比較的制御不可能な致命的なエラーが発生する可能性があります。
実際、Go がリリースされた直後 (Go 1.0 がリリースされるずっと前) 2009 年の時点で、一部の人々が関連する疑問を提起し、この問題の解決を望んでいた:
最後に、今後の Go 1.17 では、仕様を更新するコミット ID #1c268431f4 で始まる一連の変更により、これが可能になります。
新しい仕様でのこれの説明は非常に簡単です:
スライスを配列ポインターに変換すると、スライスの基になる配列へのポインターが生成されます。スライスの長さが配列の長さより短い場合、実行時パニックが発生します。
- スライスが配列の長さより長い場合は、無害であり、発生する可能性があります。普通に走ります。
- スライスが配列より長い場合は、配列が元のスライスのサポートされているすべての配列にアクセスできないことを意味します。
s := make([]byte, 2, 4) s0 := (*[0]byte)(s) // s0 != nil s2 := (*[2]byte)(s) // &s2[0] == &s[0] s4 := (*[4]byte)(s) // panics: len([4]byte) > len(s) var t []string t0 := (*[0]string)(t) // t0 == nil t1 := (*[1]string)(t) // panics: len([1]string) > len(s)
- 変数 s2 の変換: 基になる配列をスライスします。つまり、この変換では新しい配列が割り当てられない (割り当てられない) ため、効率が確保されます。
- 変数 s0 と t0 の変換: 空ではないフラグメントを長さ 0 の配列に変換します。長さ 0 の配列では何もできませんが、有効なポインタ (nil) を与える必要があります。
、あるいは落とし穴に遭遇したことはありますか? みなさんもコメント欄にメッセージを残してコミュニケーションをとっていただければ幸いです。
その他の golang 関連の技術記事については、