구글에서string이 []byte에 분배되어도 필기 복사를 하지 않는 방법을 고려해 보자

6812 단어 Go
추기9에서 이 방법을 사용하면 동작을 안정시키지 못할 수도 있다
  • 구글에서 string을 []byte에 할당하면 노트 복사가 시작됩니다. - Qita
  • 비고: 구글에서 투명하게 []byte와string으로 읽는 파일럿 오류 처리 - Qita
  • 복사하지 않을 방법이 없을 것 같아서 펜을 찾았어요.
    구글에서 []byte(str) 컴파일할 때 runtime.gostringtoslicebyte 에 따라 바이트 배열에 복사됩니다.
    runtime.go
    func stringtoslicebyte(s string) []byte {
        b := rawbyteslice(len(s))
        copy(b, s)
        return b
    }
    
    그러나 실제로 구글은 내부적으로utf-8 문자열을 처리하기 때문에 직접 꺼내는 방법만 있으면 된다.
    그래서 unsafe 등장했어요...

    이걸 사용하면 스스로 프로그램을 파괴할 수 있어.

    내부의 바이트는 말할 필요가 없다...
    stringbytes.go
    package main
    
    import (
        "fmt"
        "unsafe"
    )
    
    func main() {
        str := "hello, world!"
        vec := *(*[]byte)(unsafe.Pointer(&str))
        fmt.Println(vec)
    }
    
    포인터 연산까지 가능합니다!
    pointer.go
    package main
    
    import (
        "unsafe"
    )
    
    type foo struct {
        k int64
        v int64
    }
    
    func main() {
        f := &foo{3,4}
    
        // unsafe.Pointer() で匿名ポインタにして
        // uintptr() で演算可能にして
        // +8 バイト(64bit)足して
        // unsafe.Pointer で匿名ポインタに戻して
        // そこにはフィールド v があるはずなので *int64 にキャストして
        // デリファレンスすれば出来上がり
        *(*int64)(unsafe.Pointer((uintptr(unsafe.Pointer(f))+8))) = 5 // グヒヒ
    
        println(f.v) // 5
    }
    
    
    참고로 상술한 stringbytes.gogo tool 8g -S stringbytes.go에서 어셈블러를 만들어 보면...
        0x001c 00028 (stringbytes2.go:8)    LEAL    go.string."hello, world!"+0(SB),BX
        0x0022 00034 (stringbytes2.go:8)    MOVL    (BX),CX
        0x0024 00036 (stringbytes2.go:8)    MOVL    4(BX),BP
        0x0027 00039 (stringbytes2.go:9)    MOVL    CX,"".str+24(SP)
        0x002b 00043 (stringbytes2.go:9)    MOVL    CX,(SP)
        0x002e 00046 (stringbytes2.go:9)    MOVL    BP,"".str+28(SP)
        0x0032 00050 (stringbytes2.go:9)    MOVL    BP,4(SP)
        0x0036 00054 (stringbytes2.go:9)    PCDATA  $0,$0
        0x0036 00054 (stringbytes2.go:9)    CALL    ,runtime.stringtoslicebyte(SB)
        0x003b 00059 (stringbytes2.go:9)    MOVL    8(SP),DX
        0x003f 00063 (stringbytes2.go:9)    MOVL    12(SP),CX
        0x0043 00067 (stringbytes2.go:9)    MOVL    16(SP),AX
    
    ※ 부분 발췌문
    이렇게 전선에 떨어진 건...
        0x001c 00028 (stringbytes.go:9) LEAL    go.string."hello, world!"+0(SB),BX
        0x0022 00034 (stringbytes.go:9) MOVL    (BX),BP
        0x0024 00036 (stringbytes.go:9) MOVL    BP,"".str+24(SP)
        0x0028 00040 (stringbytes.go:9) MOVL    4(BX),BP
        0x002b 00043 (stringbytes.go:9) MOVL    BP,"".str+28(SP)
        0x002f 00047 (stringbytes.go:10)    LEAL    "".str+24(SP),BX
        0x0033 00051 (stringbytes.go:10)    CMPL    BX,$0
        0x0036 00054 (stringbytes.go:10)    JEQ $1,232
        0x003c 00060 (stringbytes.go:10)    MOVL    (BX),DX
        0x003e 00062 (stringbytes.go:10)    MOVL    4(BX),CX
        0x0041 00065 (stringbytes.go:10)    MOVL    8(BX),BP
    
    이렇게 생겼어!
    이렇게 하면 복사를 하지 않아도 문자열을 처리할 수 있다!
    프로그램도 빨라졌어!
    아무도 난처하지 않아!
    모두 즐겁다!
    모두들 힘껏 사용해라!

    unsafe를 사용할 때 사용법과 용량을 엄격히 준수하십시오.레이스 컨디션이고 모든 경우에도 GC-safe가 아닙니다.

    좋은 웹페이지 즐겨찾기