I'd like to get the value of all the fields in a struct that aren't empty. This works for simple primitives (string
, int
, etc.), but not for struct types such as sql.NullString
.
Very simple example:
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)
}
This gives a panic:
panic: interface conversion: interface is reflect.Value, not sql.NullString
I don't understand this, since the Interface
method should return an interface{}
(and not a reflect.Value
) which I can then type assert (?)
First I thought I was maybe using type conversions only works for primitives, but a quick test script:
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
", iface, iface)
fmt.Printf("%T -> %#v -> %#v
", iface.(sql.NullString), iface.(sql.NullString),
iface.(sql.NullString).Valid)
}
Reveals that this should work?
The full code I'm using:
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>
",
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
",
fieldType.Name, iface, iface)
// panic: interface conversion: interface is reflect.Value, not sql.NullString
iface2 := v.Interface().(sql.NullString)
fmt.Printf("%s: %T -> %#v
",
fieldType.Name, iface2, iface2)
}
}
}
fmt.Printf(changed)
}