Closed9

省メモリでstringを反転(Go)

tenkohtenkoh

前提

  • ヒープに置かれたstring型の文字列がある
  • 文字は全て1byte文字なので、runeにする必要はない
  • できるだけ(曖昧)省メモリにする
tenkohtenkoh

お察しのように競プロあるいはアルゴリズムの文脈

tenkohtenkoh

もし[]byteだったら

何も難しいことはなく、こんな感じでおしまい

tenkohtenkoh
b := []byte("abc")

for i := 0; i < len(b)/2; i++ {
	b[i], b[len(b)-1-i] = b[len(b)-1-i], b[i]
}
tenkohtenkoh

これがstringで渡されてくると、stringはイミュータブルなので困ってしまう。

ということでunsafeを使った黒魔術が必要な見込み。

tenkohtenkoh

以下のような関数で、stringの先頭アドレスとその長さを持った[]byteが作れるので、そいつに先ほどのような反転処理をかませばよい。(もちろんマルチバイト文字が無い前提でしか使えない)

func StringToBytes(s string) []byte {
    return unsafe.Slice(unsafe.StringData(s), len(s))
}
tenkohtenkoh

作った[]byteを操作すれば元のstringをいじれる。元のstringがスタックに置かれているとパニックする。そりゃそうですよねぇ…。さすがunsafeだぜ!(変なテンション)

tenkohtenkoh

結論:前工程と良く相談して「本当にstringで渡さないかんの!?[]byteじゃいかんの!?」と問い詰めましょう。

このスクラップは2023/09/30にクローズされました