2017-05-02 2 views
0

Go의 반사 패키지를 사용하면 포인터가 nil 인 경우 구조체에 포인터를 설정하는 방법이 있습니까? 반영 패키지를보고 reflect.Value.CanSet()false이면 Set() 호출은 패닉을 초래합니다. 이 문제를 해결하는 다른 방법이 있습니까? 구조체에 대한 직접적인 참조에 의존하지 않고 반영 패키지 만 사용합니까? 예를 들어 아래 코드에서 비어있는 성을 "존슨"으로 설정하려면 어떻게해야합니까? 당신이 LastName 필드에 값을 설정해야하기 때문에Golang이 구조체에 nil 문자열 포인터 값을 설정합니다.

package main 

import (
    "fmt" 
    "reflect" 
) 

type Person struct { 
    FirstName *string 
    LastName *string 
} 

func main() { 
    p := Person{} 
    firstName := "Ryan" 
    p.FirstName = &firstName 

    rp := reflect.ValueOf(p) 
    fmt.Println("rp:", rp) 

    for i := 0; i < rp.NumField(); i++ { 
     fmt.Printf("%s: Pointer: %d CanSet: %t\n", rp.Type().Field(i).Name, rp.Field(i).Pointer(), rp.Field(i).Elem().CanSet()) 
    } 

    rp.Field(0).Elem().SetString("Brian") 
    fmt.Println(*p.FirstName) 

    // Yields nil pointer error 
    // rp.Field(1).Elem().SetString("Johnson") 
    // fmt.Println(*p.LastName) 

    fmt.Println(rp.Field(1).Type()) 
    fmt.Println(rp.Field(1).CanSet()) 
    // fmt.Println(rp.Field(1).Elem().Type()) // nil pointer here also 
    fmt.Println(rp.Field(1).Elem().CanSet()) 
} 

See in Golang Playground

+0

여기 뻔한 질문을 것입니다. .. 왜 이걸하고 싶니? 나 자신은 문자열에 대한 포인터를 사용하는 많은 이유를 본 적이 없으며 표준 라이브러리에서 사용 된 것도 본 적이 없다. – RayfenWindspear

+1

공정한 질문입니다. REST API를 노출하면 클라이언트가 필드를 제공했는지 여부를 알 수 있습니다. 포인터가 아니라면 문자열의 빈 값은'' "'입니다. 그렇다면 클라이언트는''''을 제공 했습니까? 아니면 아무것도 제공하지 않았습니까? 또한, 'Validate'와 'Transform'과 같은 구조체 필드에 고유 태그를 추가하고 있습니다. 그래서, 나는 그들을 반영하기 위해 거기에 반영 패키지를 사용하고 있습니다. –

답변

5

당신은 먼저 Person{}에 대한 포인터가 필요합니다.

p := &Person{} 

그런 다음 당신은 당신이 문자열 값을 설정할 수 있도록합니다 LastName 필드에 유효한 포인터 값을 설정할 수 있습니다

rp.Field(1).Set(reflect.New(rp.Field(1).Type().Elem())) 
rp.Field(1).Elem().SetString("Jones") 

https://play.golang.org/p/f5MjpkDI2H

관련 문제