Programmingバックエンド開発者

Goにおける不変(immutable)および可変(mutable)データ構造の扱いはどのようになっていますか?プログラミング時にこの点を考慮すべき例を挙げてください。

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

回答

Goでは、ほとんどの組み込みデータ型(例えば、intfloatstruct)は、変数として宣言されると**可変(mutable)**です。なぜなら、値渡しで渡すと、構造体全体や値がコピーされるからです。しかし、重要な点があります:スライス(slice)、マップ(map)、チャネル(channel)は、内部データストレージのロジックを持つ参照型です。

基本的な型:

x := 10 y := x // ここで値のコピーが作成され、xとyは互いに影響しない y = 20 // xは10のまま

スライス:

a := []int{1,2,3} b := a // 同じ基本配列のスライスへの参照 b[0] = 100 // これでa[0]も100になる

関数やメソッドが構造体やスライスを受け取る場合、重要です。変更が元のデータに影響を与えるかどうかは、データ型と渡し方(値渡しか参照渡しか)によります。

トリックのある質問

質問: 「スライスを別のスライスに割り当てると、深いコピーが得られますか、それとも両方が同じデータを指しますか?」

回答: スライスの単純な割り当て(b := a)では、両方が同じ基本配列を指し示しますが、長さと容量は独立しています。一方のスライスから配列のデータを変更すると、もう一方に反映されます。

例:

a := []int{1,2,3} b := a b[0] = 42 fmt.Println(a) // [42 2 3]

深いコピーを作成するには、copyを使用します:

c := make([]int, len(a)) copy(c, a) c[0] = 99 fmt.Println(a) // [42 2 3], cは独立したコピー

逸話

データフィルタリングサービスが予期しない結果を返した: 一人の開発者がスライスを複数の関数間でコピーせずに渡し、その状態を変更していました。このため、異なる場所でのスライスの変更がアプリケーションのロジックを壊し、奇妙なデータバグが長い間見つからなかったのです。


逸話

構造体渡し後のデータ損失: 一つのプロジェクトで、データをシリアル化する際に必須フィールドを構造体から誤って削除しました。これは、オブジェクトが参照で渡され、コピーが作成されなかったからです。この結果、運用環境で重要な情報が失われました。


逸話

マップの並列処理に関するエラー: 開発者はマップへの参照をコピーし、変更が元のものに影響しないと考えましたが、これは他の言語では違う場合があります。その結果、異なるゴルーチンでデータ競合が発生し、アプリケーションがクラッシュしました。