2016-07-03 1 views
0

비어 있지 않은 구조체의 모든 필드 값을 가져오고 싶습니다. 이 간단한 기본 (string, int, 등) 있지만 구조체 형식에 대한 sql.NullString 같은 작동하지 않습니다.리플렉션을 사용하여 sql.NullString 값 가져 오기

아주 간단한 예 :이 패닉 제공

package main 

import (
    "database/sql" 
    "fmt" 
    "reflect" 
) 

func main() { 
    type fooT struct { 
     NullS sql.NullString 
    } 

    values := reflect.ValueOf(fooT{}) 

    field := values.Field(0) 
    v := reflect.ValueOf(field) 

    iface := v.Interface().(sql.NullString) 

    fmt.Println(iface) 
} 

다음 Interface 방법은 반환해야하기 때문에,

panic: interface conversion: interface is reflect.Value, not sql.NullString 

나는이 이해가 안 돼요을 interface{} (아닌 reflect.Value)하는 I

첫 번째로 나는 유형 변환을 사용하고 있을지도 모르겠지만, 프리미티브에만 사용할 수 있다고 생각했지만 빠른 테스트 스크립트 :

package main 

import (
    "database/sql" 
    "fmt" 
) 

func main() { 
    type fooT struct { 
     NullS sql.NullString 
    } 

    foo := fooT{NullS: sql.NullString{"It's an Aardvark!", true}} 

    var iface interface{} 
    iface = foo.NullS 

    fmt.Printf("%T -> %#v\n", iface, iface) 
    fmt.Printf("%T -> %#v -> %#v\n", iface.(sql.NullString), iface.(sql.NullString), 
     iface.(sql.NullString).Valid) 
} 

이렇게하면 효과가 있음을 알 수 있습니까? 내가 사용


전체 코드 :

package main 

import (
    "database/sql" 
    "fmt" 
    "reflect" 
) 

type fooT struct { 
    ID int64 
    Foo string 
    NullS sql.NullString 
    FooQ sql.NullString 
} 

func main() { 
    foo := fooT{ 
     ID: 42, 
     NullS: sql.NullString{"Your mother was a hamster", true}, 
    } 

    types := reflect.TypeOf(foo) 
    values := reflect.ValueOf(foo) 

    changed := "" 
    for i := 0; i < types.NumField(); i++ { 
     fieldType := types.Field(i) 
     field := values.Field(i) 

     switch field.Type().Kind() { 
     // Works 
     case reflect.String: 
      if field.String() != "" { 
       changed += fmt.Sprintf("<strong>%s</strong>: %v<br>\n", 
        fieldType.Name, field.String()) 
      } 
     default: 
      switch field.Type().String() { 
      case "sql.NullString": 
       v := reflect.ValueOf(field) 

       // NullS: reflect.Value -> sql.NullString{String:"Your mother was a hamster", Valid:true} 
       iface := v.Interface() 
       fmt.Printf("%s: %T -> %#v\n", 
        fieldType.Name, iface, iface) 

       // panic: interface conversion: interface is reflect.Value, not sql.NullString 
       iface2 := v.Interface().(sql.NullString) 
       fmt.Printf("%s: %T -> %#v\n", 
        fieldType.Name, iface2, iface2) 
      } 
     } 
    } 

    fmt.Printf(changed) 
} 
+0

감사 완성 된 프로그램을 포함합니다. NullString의 경우에는'reflect.ValueOf'가 필요하지 않다고 생각합니다. (참고로, 문자열의 경우는 없습니다.) 질문을 오해하고있을 수도 있지만 몇 가지 코드 샘플을 사용하여 답변을 게시 할 것입니다. – twotwotwo

답변

1

나는 문제가 추가 reflect.ValueOf 당신이하지 NullString에, 또 다른 reflect.Value 참조하는 reflect.Value을 한 것으로 의미가 있다고 생각합니다. 방법은 Printf 일종의 그것을 가려서 형식화. values.Field(i)reflect.Value이 필요합니다. Here's your program은 최소한으로 ValueOf을 복용에 의해 수정 :

package main 

import (
    "database/sql" 
    "fmt" 
    "reflect" 
) 

type fooT struct { 
    ID int64 
    Foo string 
    NullS sql.NullString 
    FooQ sql.NullString 
} 

func main() { 
    foo := fooT{ 
     ID: 42, 
     NullS: sql.NullString{"Your mother was a hamster", true}, 
    } 

    types := reflect.TypeOf(foo) 
    values := reflect.ValueOf(foo) 

    changed := "" 
    for i := 0; i < types.NumField(); i++ { 
     fieldType := types.Field(i) 
     field := values.Field(i) 

     switch field.Type().Kind() { 
     // Works 
     case reflect.String: 
      if field.String() != "" { 
       changed += fmt.Sprintf("<strong>%s</strong>: %v<br>\n", 
        fieldType.Name, field.String()) 
      } 
     default: 
      switch field.Type().String() { 
      case "sql.NullString": 
     iface := field.Interface() 
       fmt.Printf("%s: %T -> %#v\n", 
        fieldType.Name, iface, iface) 
      } 
     } 
    } 

    fmt.Printf(changed) 
} 

당신은, 대부분의 작업을 할 like sotype switch를 사용하여 더 간단하게 할 수 있습니다 :

package main 

import (
    "database/sql" 
    "fmt" 
    "reflect" 
) 

type fooT struct { 
    ID int64 
    Foo string 
    NullS sql.NullString 
    FooQ sql.NullString 
} 

func main() { 
    foo := fooT{ 
     ID: 42, 
     NullS: sql.NullString{"Your mother was a hamster", true}, 
    } 

    values := reflect.ValueOf(foo) 

    changed := "" 
    for i := 0; i < values.NumField(); i++ { 
     v := values.Field(i) 
     f := v.Interface() 
     switch f := f.(type) { 
     case string: 
      fmt.Println("string:", f) 
     case sql.NullString: 
      fmt.Println("NullString:", f.Valid, f.String) 
     default: 
      fmt.Printf("%s: %v\n", v.Type(), f) 
     } 
    } 

    fmt.Printf(changed) 
} 
관련 문제