template won't evaluate fields that are interface type as the underlying type - interface

Using golang html/template (same behavior with text/template). If I have a struct with a member that is of an interface type, I cannot access members of the underlying type (specifically trying to access fields that are on a struct that implements interface InnerInterface but is return via the InnerInterface interface type, not the struct type).
http://play.golang.org/p/ZH8wSK83oM
package main
import "fmt"
import "os"
import "html/template"
type InnerInterface interface{ InnerSomeMethod() }
type MyInnerStruct struct { Title string }
func (mis MyInnerStruct)InnerSomeMethod() { fmt.Println("Just to show we're satisfying the interface") }
type MyOuterStruct struct { Inner InnerInterface }
func main() {
fmt.Println("Starting")
arg := MyOuterStruct{Inner:MyInnerStruct{Title:"test1"}}
err := template.Must(template.New("testtmpl").Parse("{{.Inner.Title}}")).Execute(os.Stdout, arg)
if err != nil { panic(err) }
}
Changing: type MyOuterStruct struct { Inner InnerInterface } to a totally generic interface, i.e. type MyOuterStruct struct { Inner interface{} } makes it render properly. This leads me to believe that interface{} is treated specially by the rendering engine.
Is there a better way to do this than to use interface{} whenever I want to be able to dynamically evaluate fields like this?

You're correct with saying that interface{} is handled differently by the rendering
engine. Only interface{} values are unpacked, interface values that have a method set are not.
I suppose the reasoning behind this is that if you have a interface type, you specifically limit the type to the method set. Therefore, you don't want the template engine trying to access members that may lie behind that interface.
The 'problem' is caused by the function indirect in exec.go:
func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() {
if v.IsNil() {
return v, true
}
if v.Kind() == reflect.Interface && v.NumMethod() > 0 {
break
}
}
return v, false
}
This method is called to get to the deepest value of a reflected value.
Suppose you have a pointer on a pointer on a pointer, this function will get return the
last of these. The same goes for interface values. The crux is that as soon as a
interface value has more than 0 methods, the indirection stops there. Exactly the
behaviour you're describing.
As this seems to be intended behaviour, what you can do is to define a Title() string
method in your interface and let it return the string.

Related

Validate field based on value of a different field with validator.v2

I have the following (simplified) struct:
type newAppRegister struct {
SomeFlag *bool `json:"someflag" validate:"nonnil"`
ComputeLevel string `json:"compute-level" validate:"computelevelvalidator"`
}
And computelevelvalidator is some validation function.
I want that if SomeFlag is false, then ComputeLevel will be required and run his validation function.
A possible solution is to create a static variable, and set it in a custom validation function of SomeFlag, so for example:
var someFlag bool
func someFlagValidator(v interface{}, param string) error {
st := reflect.ValueOf(v)
if st.Kind() != reflect.Bool {
return fmt.Errorf("must be bool")
}
someFlag = st.Bool()
return nil
}
And then in computelevelvalidator it's possible to condition based on his value.
But since this is a REST API, and it may receive plenty of calls per second, I'm not sure if using this static variable will work (I'm worried about race conditions - but I'm not quite sure about it).
I'm using go1.11 and validation package gopkg.in/validator.v2 (version gopkg.in/validator.v2 v2.0.0-20190827175613-1a84e0480e5b).
So first up: Yes, using this static (global) variable will be a problem for concurrent use/access. It's not the way to go.
If your validation logic is contextual (like you said: if the flag is false, then certain restrictions apply on another field), then implementing a simple Validate function is pretty straightforward. I know the package you use supports this type of thing, but an external package will almost always be designed to be fairly generic. At the very least you'll end up performing type assertions. Last I checked, you still need an explicit call for the validation validator.Validate(), so why not move that to a method on your type?
type newAppRegister struct {} // your type
func (n newAppRegister) Validate() error {
if err := validator.Validate(n); err != nil {
return err
}
// at this point, we now the flag field isn't nit, because it passed validation
if !*n.SomeFlag {
// validate ComputeLevel here
}
return nil
}
No need for type assertions, let alone reflection. With just these two fields, I'd even argue there's no need for the validator package at all. You can get the same thing done with just standard JSON tags:
type Foo struct {
SomeFlag *bool `json:"some_flag,omitempty"`
ComputeLevel string `json:"compute_level"`
}
func (f Foo) Validate() error {
if f.SomeFlag == nil {
return ErrSomeFlagRequired
}
if !*f.SomeFlag {
// validate ComputeLevel
}
return nil
}
It's fairly straightforward to use:
f := Foo{}
if err := json.Unmarshal([]byte(payload), &f); err != nil {
// some shady JSON was submitted
}
if err := f.Validate(); err != nil {
// JSON was technically valid, but payload made no sense
}
// handle valid request

Addressing potential null fields in go's sqlx [duplicate]

Go types like Int64 and String cannot store null values,
so I found I could use sql.NullInt64 and sql.NullString for this.
But when I use these in a Struct,
and generate JSON from the Struct with the json package,
then the format is different to when I use regular Int64 and String types.
The JSON has an additional level because the sql.Null*** is also a Struct.
Is there a good workaround for this,
or should I not use NULLs in my SQL database?
Types like sql.NullInt64 do not implement any special handling for JSON marshaling or unmarshaling, so the default rules apply. Since the type is a struct, it gets marshalled as an object with its fields as attributes.
One way to work around this is to create your own type that implements the json.Marshaller / json.Unmarshaler interfaces. By embedding the sql.NullInt64 type, we get the SQL methods for free. Something like this:
type JsonNullInt64 struct {
sql.NullInt64
}
func (v JsonNullInt64) MarshalJSON() ([]byte, error) {
if v.Valid {
return json.Marshal(v.Int64)
} else {
return json.Marshal(nil)
}
}
func (v *JsonNullInt64) UnmarshalJSON(data []byte) error {
// Unmarshalling into a pointer will let us detect null
var x *int64
if err := json.Unmarshal(data, &x); err != nil {
return err
}
if x != nil {
v.Valid = true
v.Int64 = *x
} else {
v.Valid = false
}
return nil
}
If you use this type in place of sql.NullInt64, it should be encoded as you expect.
You can test this example here: http://play.golang.org/p/zFESxLcd-c
If you use the null.v3 package, you won't need to implement any of the marshal or unmarshal methods. It's a superset of the sql.Null structs and is probably what you want.
package main
import "gopkg.in/guregu/null.v3"
type Person struct {
Name string `json:"id"`
Age int `json:"age"`
NickName null.String `json:"nickname"` // Optional
}
If you'd like to see a full Golang webserver that uses sqlite, nulls, and json you can consult this gist.

Generic constrained type default value

Consider the following code:
protocol JSONParserType {
associatedtype Element
}
// MARK: - Entities
struct Item {}
// MARK: - Parsers
struct OuterParser<T: JSONParserType where T.Element == Item>: JSONParserType {
typealias Element = Item
let innerParser: T
init(innerParser: T = InnerParser()) {
self.innerParser = innerParser
}
}
struct InnerParser: JSONParserType {
typealias Element = Item
}
The OuterParser has a child parser that should be constrained to a specific type. Unfortunately providing a default value in the initializer (or in the property definition itself) does lead to the compiler throwing a "Default argument value of type 'InnerParser' cannot be converted to type 'T'".
If I remove the default value assignment and just instantiate the OuterParser providing the InnerParser explicitly, everything is fine.
let outerParser = OuterParser(innerParser: InnerParser())
My question is what's the reason that the approach providing a default value that actually meets the constraints does not work.
The problem is that the actual type of T isn't defined by the class – it's defined by the code that uses the class. It will therefore be defined before you do anything in your class (at either instance or static level). You therefore can't assign InnerParser to T, as T has already been defined to be a given type by that point, which may well not be InnerParser.
For example, let's consider that you have another parser struct:
struct AnotherParser: JSONParserType {
typealias Element = Item
}
and let's assume that your current code compiles. Now consider what would happen when you do this:
let parser = OuterParser<AnotherParser>()
You've defined the generic type to be AnotherParser – but the initialiser will try to assign InnerParser to your property (now of type AnotherParser). These types don't match, therefore it cannot possibly work.
Following the same logic, this implementation also won't work:
struct OuterParser<T: JSONParserType where T.Element == Item>: JSONParserType {
typealias Element = Item
let innerParser: T
init() {
self.innerParser = InnerParser()
}
init(innerParser: T) {
self.innerParser = innerParser
}
}
As there's no guarantee that the generic type T will be the same type as InnerParser. Sure, you can force downcast to T – but that'll just make you code crash if the types aren't compatible.
Unfortunately, there's no real clean solution to this problem. I think the best your best option is probably to create two factory methods for creating your OuterParser instance.
enum Parser {
static func createParser() -> OuterParser<InnerParser> {
return OuterParser(innerParser:InnerParser())
}
static func createParser<T>(innerParser:T) -> OuterParser<T> {
return OuterParser(innerParser:innerParser)
}
}
let innerParser = Parser.createParser() // OuterParser<InnerParser>
let anotherParser = Parser.createParser(AnotherParser()) // OuterParser<AnotherParser>
We're using an caseless enum here to avoid polluting the global namespace with extra functions.
Although this isn't very Swifty, and for that reason I would also recommend maybe rethinking your logic for how you define your parsers.
type T more like a child protocol of JSONParserType you can convert it:
init(innerParser: T = InnerParser() as! T) {
self.innerParser = innerParser
}

Overwriting behavior of embedded struct

I have a type XY that has various fields and methods (a few dozen).
type XY struct {
Name string
SomeValue int
...
}
func (xy *XY) Do1() { ... }
func (xy *XY) Do2() { ... }
func (xy *XY) Do3() { ... }
...
Now I want to define a second type that embeds XY, keeping all fields and methods. But I do want to modify a few functions.
type AB struct {
XY
}
func (ab *AB) Do2() { ... }
So far so good. Now I want to pass AB to a function that takes XY.
func SomeFunc(xy *XY) { ... }
And here's where I stumble, no polymorphism.
I can pass *AB.XY to the function, but that wouldn't make use of AB's Do2 function anymore. I could make an interface for it, which is probably the intended way, but if SomeFunc were to need near to all functions of XY, say getters of almost all fields, I'd basically need to create a copy of XY, as an interface (possible use case: I'm on a server and have to send values to a client in a specific way). I wouldn't want to only make it an interface, because I'd have to redefine all fields and functions in all types that are using the interface.
I can think of solutions for this problem, e.g. making Do2 a closure, that is set depending on the "host" type, or an enum field in XY and changing the behavior of Do2 based on that "type" variable, or using reflection and interface{} in SomeFunc, but I'd like to know what the "correct" way in Go would be. How do you do this in the most efficient way, even if you have a lot of functions?
The correct way to do it in Go is to use interfaces. Create an interface of Do1, Do2, etc. and make SomeFunc work with the interface type.
Like #Ainar-G said, using an interface is the proper way for that kind of behavior, for example:
type Doer interface {
Do1()
Do2()
}
func (*S1) Do1() {
println("S1.Do1")
}
func (*S1) Do2() {
println("S1.Do2")
}
type S2 struct{ S1 }
func (*S2) Do1() {
println("S2.Do1")
}
func DoIt(d Doer) {
d.Do1()
d.Do2()
// you can use a type switch for specific corner cases, or implement a MarshalJson (or similar) interface for you types)
switch v := d.(type) {
case *S1:
println("Special case for S1", v)
case *S2:
println("Special case for S2", v)
}
}
playground

How do you get struct value on unknown interface{}

If I have a struct and I want to get it's key, but it's currently of type interface{} how do I do that?
Currently I get the following compilation error:
invalid operation: d[label] (index of type interface {})
Play: http://play.golang.org/p/PLr91d55GX
package main
import "fmt"
import "reflect"
type Test struct {
s string
}
func main() {
test := Test{s: "blah"}
fmt.Println(getProp(test, "s"))
}
func getProp(d interface{}, label string) (interface{}, bool) {
switch reflect.TypeOf(d).Kind() {
case reflect.Struct:
_, ok := reflect.TypeOf(d).FieldByName(label)
if ok {
// errors here because interface{} doesn't have index of type
return d[label], true
} else {
return nil, false
}
}
}
Do I really have to do the massive case statement on each different type and call the reflected reflect.ValueOf(x).String() etc? I'm hoping there is a more elegant way.
You could do this, however I think it'll only work if your struct member s was an exported field (i.e. use a capital S in your example)
func getProp(d interface{}, label string) (interface{}, bool) {
switch reflect.TypeOf(d).Kind() {
case reflect.Struct:
v := reflect.ValueOf(d).FieldByName(label)
return v.Interface(), true
}
return nil, false
}
(+ some more error handling)
I'm not sure exactly what you're looking for, but there is a slightly simpler way to look for interface{} types. In your case, you could use:
switch val := d.(type) {
case Test:
fmt.Println(d.s)
}
Obviously, I'm not doing the same thing as you were, but the idea is that you can check the type with "d.(type)", and once "case Test:" determines that it is a struct of your Test type, you can access it as such.
Unfortunately, this doesn't address the accessing of the value within the struct by the label, but it at least is a more elegant way of determining the type, and #nos shows how to do that with
v := reflect.ValueOf(d).FieldByName(label)
return v.Interface(), true