ProgrammingGo開発者

Goにおける文字列(string)の扱いに関する注意事項は何ですか?プログラミング中の予期しないエラーを避けるために必要な点は?

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

回答。

問題の歴史: Goの文字列(string)は基本的で頻繁に使用されるタイプで、データの交換、ログ出力、パースなどで積極的に使用されます。Goの特徴は、文字列が不変であり、変更できないバイトのシーケンスで構成され、UTF-8でデータを含むことができる点です。

問題: 文字列とバイトスライス([]byte)の扱いが混乱し、文字列の変更やルーン(rune)でのスライス、マルチバイト文字に対する操作(例: キリル文字、絵文字)時にエラーが発生します。

解決策:

文字列は不変であり、要素を直接変更することはできません。s[0]を変更しようとするとエラーになります。文字列はUTF-8でエンコードされており、1つの文字(ルーン)は1バイトよりも広い場合があります。[]byteでの作業はより安価ですが、手動での管理が必要です。string <-> []byteの変換は常にコピーを作成します。

コード例:

s := "こんにちは" fmt.Println(len(s)) // 15バイト(キリル文字:2バイトずつ) fmt.Println(len([]rune(s))) // 6ルーン、文字数 fmt.Println(string([]byte{228, 189, 160, 229, 165, 189})) // 中国の漢字

重要な特徴:

  • 文字列は不変で、インデックスによる変更はできません。
  • 文字列はUTF-8でエンコードされており、必ずしも1文字 = 1バイトではありません。
  • string <-> []byteの変換はコピーを作成します。

間違った質問。

1. インデックスを介して文字列の特定の文字を変更できますか(例えば、s[1] = 'a')?

答え: いいえ。文字列は不変であり、コンパイラはエラーを返します。新しいスライス[]runeまたは[]byteを作成して変更し、その後再び文字列に変換する必要があります。

2. なぜlen(str)が常に文字列内の文字の数と一致しないのですか?

答え: len(str)はバイト数であり、ルーン(文字数)ではありません。キリル文字や絵文字の場合、長い文字列は直感的に予想外の値を返す可能性があります。文字数を数えるには[]runeを使用します:

s := "世界 😀" fmt.Println(len(s)) // 7 fmt.Println(len([]rune(s))) // 5

3. 文字列は関数に渡すときに参照渡しですか、それとも値渡しですか?

答え: 値渡しですが、実際にはメモリへのポインタと長さが内部に保存されています。渡された後、2つの変数は同じテキストを指し、コピーは自動的には作成されません。実際のメモリのコピーは、[]byteへの変換やstringから[]byteへの変換時に作成されます。

一般的なエラーとアンチパターン

  • インデックスを介して文字列を直接変更しようとすること。
  • lenを介した文字列の長さ比較 — ユニコードのエラー。
  • シリアル化に[]byteを使用するが、エンコーディングを忘れること。
  • 文字列と[]byteがメモリ内で異なるオブジェクトであることを忘れること。

実生活の例

ネガティブケース

開発者がロシア語の文字列で最初の4バイトを取得し、最初の文字を得られると期待するが、文字の半分しか得られず、「壊れた」文字が得られる。

メリット: 迅速かつ短い結果が得られた。 デメリット: Unicodeデータの不正な処理、壊れた文字列、他の場所でそのような文字列をパースしようとした際のパニック。

ポジティブケース

文字列はキャラクターを扱うために[]runeに変換され、必要な操作が行われた後、再びstring()を介して文字列が構築される。[]byteでの作業は、エンコーディングを考慮した低レベルのシリアル化のためのみに行われる。

メリット: Unicodeの正しい処理、関数の信頼性。 デメリット: わずかに遅く、より多くのメモリを必要としますが、どの文字列に対しても安全です。