Programing

reflect를 사용하여 struct 필드의 값을 어떻게 설정합니까?

lottogame 2020. 9. 3. 23:39
반응형

reflect를 사용하여 struct 필드의 값을 어떻게 설정합니까?


reflect패키지를 사용하여 구조체 필드로 작업하는 데 어려움을 겪고 있습니다. 특히 필드 값을 설정하는 방법을 찾지 못했습니다.

유형 t struct {fi int; fs 문자열}
var rt = t {123, "jblow"}
var i64 int64 = 456
  1. 필드 i의 이름 가져 오기-작동하는 것 같습니다

    var field = reflect.TypeOf(r).Field(i).Name

  2. 필드 i의 값을 a) 인터페이스 {}, b) int-작동하는 것 같습니다.

    var iface interface{} = reflect.ValueOf(r).Field(i).Interface()

    var i int = int(reflect.ValueOf(r).Field(i).Int())

  3. 필드 i의 값 설정-시도해보기-패닉

    reflect.ValueOf(r).Field(i).SetInt( i64 )

    panic : 반출되지 않은 필드를 사용하여 얻은 값을 사용하여 reflect.Value · SetInt

    필드 이름 "id"및 "name"이 마음에 들지 않는다고 가정하여 "Id"및 "Name"으로 이름이 변경되었습니다.

    a)이 가정이 맞습니까?

    b) 맞다면 같은 파일 / 패키지에서 필요하지 않다고 생각했습니다.

  4. 필드 i의 설정 값-두 번 시도 (필드 이름이 대문자로 표시됨)-패닉

    reflect.ValueOf(r).Field(i).SetInt( 465 )

    reflect.ValueOf(r).Field(i).SetInt( i64 )

    panic : 주소를 지정할 수없는 값을 사용하는 reflect.Value · SetInt


@peterSO의 아래 지침은 철저하고 고품질입니다.

네. 이것은 작동합니다 :

reflect.ValueOf(&r).Elem().Field(i).SetInt( i64 )

그는 필드 이름을 내보낼 수 있어야한다고 문서화합니다 (대문자로 시작).


Go는 오픈 소스 코드 로 제공됩니다 . 리플렉션에 대해 배우는 좋은 방법은 핵심 Go 개발자가 리플렉션을 사용하는 방법을 확인하는 것입니다. 예를 들어 Go fmtjson 패키지가 있습니다. 패키지 문서에는 패키지 파일 제목 아래에 소스 코드 파일에 대한 링크가 있습니다.

Go json 패키지는 Go 구조에서 JSON을 마샬링하고 언 마샬링합니다.


다음은 struct오류를 조심스럽게 피하면서 필드 값을 설정하는 단계별 예제입니다 .

Go reflect패키지에는 CanAddr기능이 있습니다.

func (v Value) CanAddr() bool

Addr로 값의 주소를 얻을 수있는 경우 CanAddr은 true를 반환합니다. 이러한 값을 주소 지정 가능이라고합니다. 값은 슬라이스의 요소, 주소 지정 가능한 배열의 요소, 주소 지정 가능한 구조체의 필드 또는 포인터 역 참조의 결과 인 경우 주소를 지정할 수 있습니다. CanAddr이 false를 반환하면 Addr을 호출하면 패닉이 발생합니다.

이동의 reflect패키지는이 CanSet경우, 기능, true즉 의미 CanAddr도입니다 true.

func (v Value) CanSet() bool

CanSet은 v 값을 변경할 수있는 경우 true를 반환합니다. 값은 주소 지정이 가능하고 내 보내지 않은 구조체 필드를 사용하여 얻지 못한 경우에만 변경할 수 있습니다. CanSet이 false를 반환하면 Set 또는 유형별 setter (예 : SetBool, SetInt64)를 호출하면 패닉이 발생합니다.

우리 Setstruct현장에서 할 수 있는지 확인해야 합니다. 예를 들면

package main

import (
    "fmt"
    "reflect"
)

func main() {
    type t struct {
        N int
    }
    var n = t{42}
    // N at start
    fmt.Println(n.N)
    // pointer to struct - addressable
    ps := reflect.ValueOf(&n)
    // struct
    s := ps.Elem()
    if s.Kind() == reflect.Struct {
        // exported field
        f := s.FieldByName("N")
        if f.IsValid() {
            // A Value can be changed only if it is 
            // addressable and was not obtained by 
            // the use of unexported struct fields.
            if f.CanSet() {
                // change value of N
                if f.Kind() == reflect.Int {
                    x := int64(7)
                    if !f.OverflowInt(x) {
                        f.SetInt(x)
                    }
                }
            }
        }
    }
    // N at end
    fmt.Println(n.N)
}

Output:
42
7

If we can be certain that all the error checks are unnecessary, the example simplifies to,

package main

import (
    "fmt"
    "reflect"
)

func main() {
    type t struct {
        N int
    }
    var n = t{42}
    fmt.Println(n.N)
    reflect.ValueOf(&n).Elem().FieldByName("N").SetInt(7)
    fmt.Println(n.N)
}

This seems to work:

package main

import (
    "fmt"
    "reflect"
)

type Foo struct {
    Number int
    Text string
}

func main() {
    foo := Foo{123, "Hello"}

    fmt.Println(int(reflect.ValueOf(foo).Field(0).Int()))

    reflect.ValueOf(&foo).Elem().Field(0).SetInt(321)

    fmt.Println(int(reflect.ValueOf(foo).Field(0).Int()))
}

Prints:

123
321

참고URL : https://stackoverflow.com/questions/6395076/using-reflect-how-do-you-set-the-value-of-a-struct-field

반응형