1. ホーム
  2. go

[解決済み] Goでio.Readerから文字列へ

2022-04-25 10:11:14

質問

私は io.ReadCloser オブジェクトを作成します。 http.Response オブジェクト)を作成します。

最も効率的な方法は、ストリーム全体を string オブジェクトを作成できますか?

解決方法は?

EDITです。

1.10以降、strings.Builderが存在します。例

buf := new(strings.Builder)
n, err := io.Copy(buf, r)
// check errors
fmt.Println(buf.String())


以下、古い情報

文字列に変換するためには、バイト配列を完全にコピーする必要があるため、効率が悪いということです。以下は、あなたが望むことを行うための適切な(非効率的な)方法です。

buf := new(bytes.Buffer)
buf.ReadFrom(yourReader)
s := buf.String() // Does a complete copy of the bytes in the buffer.

このコピーは、保護機構として行われる。文字列は不変である。もし[]byteを文字列に変換することができれば、文字列の中身を変更することができます。しかし、goではunsafeパッケージを使って型安全機構を無効化することができます。unsafeパッケージの使用は自己責任でお願いします。名前だけで十分な警告になることを祈ります。以下は、私がunsafeを使用して行う方法です。

buf := new(bytes.Buffer)
buf.ReadFrom(yourReader)
b := buf.Bytes()
s := *(*string)(unsafe.Pointer(&b))

これで、バイト配列を効率よく文字列に変換することができました。実際には、型システムを騙して文字列と呼ばせているだけなのですが。この方法には2つほど注意点があります。

  1. すべてのgoコンパイラで動作する保証はありません。plan-9 gc コンパイラで動作しますが、公式仕様に記載されていない "実装の詳細" に依存しています。これがすべてのアーキテクチャで動作し、gcで変更されないことを保証することもできません。つまり、これは悪いアイデアなのです。
  2. その文字列は変更可能です! そのバッファに対して何らかの呼び出しを行った場合、それは は文字列を変更します。十分注意してください。

私のアドバイスは、正式な方法にこだわることです。コピーをすることは その 高価であり、unsafeの弊害に見合うものではありません。もし文字列が大きすぎてコピーができないなら、文字列にするべきではないでしょう。