Programing

io.Reader에서 Go의 문자열로

crosscheck 2020. 7. 15. 07:42
반응형

io.Reader에서 Go의 문자열로


나는이 io.ReadCloser(AN에서 개체 http.Response개체).

전체 스트림을 string객체 로 변환하는 가장 효율적인 방법은 무엇입니까 ?


짧은 대답은 문자열로 변환하려면 바이트 배열의 전체 사본을 수행해야하기 때문에 비효율적이라는 것입니다. 원하는 것을 수행하는 올바른 (비효율적 인) 방법은 다음과 같습니다.

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

이 사본은 보호 메커니즘으로 수행됩니다. 문자열은 변경할 수 없습니다. [] 바이트를 문자열로 변환 할 수 있으면 문자열의 내용을 변경할 수 있습니다. 그러나, 안전하지 않은 패키지를 사용하여 유형 안전 메커니즘을 비활성화 할 수 있습니다. 안전하지 않은 패키지는 사용자 책임으로 사용하십시오. 바라건대 이름만으로도 충분히 경고 할 수 있습니다. 안전하지 않은 방법으로 수행하는 방법은 다음과 같습니다.

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

이제 바이트 배열을 문자열로 효율적으로 변환했습니다. 실제로이 모든 작업은 형식 시스템이 문자열을 호출하도록 속이는 것입니다. 이 방법에는 몇 가지주의 사항이 있습니다.

  1. 이것이 모든 컴파일러에서 작동한다는 보장은 없습니다. 이것은 plan-9 gc 컴파일러와 함께 작동하지만 공식 사양에 언급되지 않은 "구현 세부 사항"에 의존합니다. 모든 아키텍처에서 작동하거나 gc에서 변경되지 않을 수도 있습니다. 다시 말해, 이것은 나쁜 생각입니다.
  2. 그 문자열은 변경 가능합니다! 해당 버퍼를 호출 하면 문자열 변경 됩니다 . 정말 조심하세요.

내 조언은 공식적인 방법을 고수하는 것입니다. 사본을 만드는 것은 그렇게 비싸지 않으며 안전하지 않은 악의 가치가 없습니다. 문자열이 복사하기에 너무 큰 경우 문자열로 만들면 안됩니다.


지금까지 답변은 질문의 "전체 스트림"부분을 다루지 않았습니다. 이 작업을 수행하는 좋은 방법은 ioutil.ReadAll입니다. 당신과 함께 io.ReaderCloser이름 rc, 나는 쓸 것이다,

if b, err := ioutil.ReadAll(rc); err == nil {
    return string(b)
} ...

가장 효율적인 방법은 항상 []byte대신에 사용하는 것입니다 string.

경우에는로부터 수신 된 데이터를 인쇄 할 필요 io.ReadCloserfmt패키지가 처리 할 수 []byte있지만, 때문에 효율적이지 않습니다 fmt구현이 내부적으로 변환됩니다 []bytestring. 이러한 변환을 피하기 위해 다음 fmt.Formatter과 같은 유형 인터페이스를 구현할 수 있습니다 type ByteSlice []byte.


data, _ := ioutil.ReadAll(response.Body)
fmt.Println(string(data))

func copyToString(r io.Reader) (res string, err error) {
    var sb strings.Builder
    if _, err = io.Copy(&sb, r); err == nil {
        res = sb.String()
    }
    return
}

bytes.Buffer 구조체가 마음에 듭니다 . ReadFromString 메소드 가 있음을 알았습니다 . 나는 그것을 [] 바이트와 함께 사용했지만 io.Reader는 사용하지 않았다.

참고 URL : https://stackoverflow.com/questions/9644139/from-io-reader-to-string-in-go

반응형