ProgrammingGo開発者

Goにおけるsliceのコピーでcopy()はどのように機能しますか?スライスの長さや容量の増加に関連する特徴、制限、不意の影響は何ですか?スライス同士が重なっている場合、重複してコピーしようとするとどうなりますか?

Hintsage AIアシスタントで面接を突破

回答

関数 copy(dst, src []T) int は、src の要素を dst にコピーします。

  • コピーされた要素の数を返します: min(len(dst), len(src))
  • インデックスでコピーが行われます: 要素 src[i]dst[i] にコピーされます。
  • コピーされるのは内容(値)であり、オブジェクトへのポインタではありません。

細かい点と制限:

  • スライスが重なっている場合(例えば、1つが他のサブ配列である場合)、コピーは最初に元の値のスニペットを取り、その後にコピーされるかのように行われます(重なりがある場合の正確性は保証されません)。
  • dst の長さが src より短い場合、dst の長さが許可するデータのみがコピーされます。
  • dst の容量が長さより大きい場合、copyでスライスを拡張しますか? — いいえ、len(dst) だけがターゲットとして考慮されます。拡張したい場合は、事前に append を使用してください。

例:

a := []int{1,2,3,4,5} b := make([]int, 3) copy(b, a) // b: [1 2 3]

重複:

x := []int{1,2,3,4} copy(x[1:], x[:3]) // [1 1 2 3]

トリッキーな質問

copy()はスライスの長さを増やすために使用できますか?コピーに対して容量が大きいが必要な長さより短いスライスを渡した場合、どうなりますか?

回答:

  • copy() はターゲットスライスの長さを変更しません — len(dst) までコピーするだけです。
  • dst に長さより大きい容量がある場合、最初に dst = dst[:newLen] で長さを拡張してから copy() を使用してください。

しばしば明白でない例:

a := []int{1,2,3} b := make([]int, 0, 5) copy(b, a) // bは空のまま、len(b)==0 b = b[:len(a)] copy(b, a) // 現在、b: [1,2,3]

知識の不足による実際のエラーの例


歴史

プロジェクトで、1つのスライスから別のスライスにデータをコピーする際、copyが自動的にdstの長さを必要なサイズまで拡張すると考えました。しかし、それは起こらず、コピーされず、APIのレスポンスにはゼロのデータが返されました。長さを比較して初めてエラーを見つけました - 問題はdstが大きな容量を持っていたが、長さが0だったことです。


歴史

マイクロサービスの一部が重なり合うスライスで機能しており、copyが常に正しく動作するだろうと誤って計算していました。その結果、前方へのコピーが元のデータを破壊し、バッファを操作する際に「見えない」バグが発生しました。一時的なバッファを使用することで解決されました(copy(tmp, src)、次にcopy(dst, tmp))。


歴史

エンジニアが配列を最適化し、スライス間のデータを並べ替えるためにcopyを使用しました。dstの長さが修正されることを期待していました。しかし、それは発生せず、パニックや有意義なデータを超える問題が発生しました — コピーする前にスライスの長さを正しく変更するのを忘れました。