Go1.15에서 온 리플렉스 포장의 행위 차이에 대해

6804 단어 Gogolangreflecttech
개인 블로그로부터의 전재.

개요


Go1.15에서reflect 패키지의 일부 행동을 바꿨습니다.여기서, Go1.14 이전에 조작된 코드는 패닉일 수 있습니다.
패닉은 비공개 구조를 포함하고 해당 구조체를 콜하는 방법을 사용하는 경우

필기를 발행하는 기술


https://golang.org/doc/go1.15#reflect
Go1.15의 발행 노트에 따르면reflect 포장에 대해 다음과 같은 기술이 있다.
Package reflect now disallows accessing methods of all non-exported fields, whereas previously it allowed accessing those of non-exported, embedded fields. Code that relies on the previous behavior should be updated to instead access the corresponding promoted method of the enclosing variable.

샘플 코드


샘플 코드는 다음과 같습니다.두 개의 구조를 정의했다.
  • 비공개unexportedStruct Print만 사용할 수 있습니다.
  • 공개된 R에는 상기 unexported Struct가 박혀 있다.
  • R을 사용하여 unexportedStruct에 액세스하는 방법의 코드입니다.오류 처리가 생략되었습니다.
    package main
    
    import (
    	"fmt"
    	"reflect"
    )
    
    type unexportedStruct struct{}
    
    func (s unexportedStruct) Print() {
    	fmt.Println("Print!")
    }
    
    type R struct {
    	unexportedStruct
    }
    
    func main() {
    	v := reflect.ValueOf(R{})
    	fmt.Printf("NumMethod=%d\n", v.Field(0).NumMethod())
    
    	method := v.Field(0).Method(0)
    	fmt.Printf("Method=%v\n", method)
    	method.Call(nil)
    }
    
    

    Go1.14와 고1.15의 차이


    다음은 행동의 차이.Go 1.14.7에서 Print 함수를 실행하고 Go1을 실행합니다.15시에 패닉이 떨어져요.

    Go 1.15


    $ go version
    go version go1.15 linux/amd64
    $ go run unexported.go 
    NumMethod=1
    Method=0x48f340
    panic: reflect: reflect.Value.Call using value obtained using unexported field
    
    goroutine 1 [running]:
    reflect.flag.mustBeExportedSlow(0x2b3)
    	/usr/local/go/src/reflect/value.go:237 +0x131
    reflect.flag.mustBeExported(...)
    	/usr/local/go/src/reflect/value.go:228
    reflect.Value.Call(0x4dd980, 0x5daf48, 0x2b3, 0x0, 0x0, 0x0, 0x1, 0x10, 0x0)
    	/usr/local/go/src/reflect/value.go:335 +0x52
    main.main()
    	/home/taka/tmp/unexported.go:22 +0x1ef
    exit status 2
    

    Go 1.14


    $ go version
    go version go1.14.7 linux/amd64
    $ go run unexported.go 
    NumMethod=1
    Method=0x488b20
    Print!
    

    수정 제출


    이 근처에요?
    https://github.com/golang/go/commit/0eb694e9c217c051cd8cc18258bf593d0be7fb8d#diff-5a4d1c9b8c6ee0bc677232e253616a23

    감상


    Go1.14까지 잘못된 행동이었으니 제대로 수정했죠.
    그러나 사용자로서 패닉 여부를 어떻게 판별하는 것이 좋을까.모두 NumMethod()의 반환값이 같고 CanCall과 같은 검사 함수도 없습니다.

    좋은 웹페이지 즐겨찾기