How do you get struct value on unknown interface{} - 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

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

Swift where condition to check if a property is implemented

I just found another way to make a great use of protocols and protocol extensions in Swift by extending the Optional protocol to add a function so I can provide default values.
I wrote a blog post about this here: https://janthielemann.de/random-stuff/providing-default-values-optional-string-empty-optional-string-swift-3-1/
The gist of the post is that I needed a clean and easy way to provide default values for optional String which are nil or empty. To do this, I created a Emptyable protocol end extended the Optional protocol like so:
protocol Emptyable {
var isEmpty: Bool { get }
}
extension Optional where Wrapped: Emptyable {
func orWhenNilOrEmpty<T: Emptyable>(_ defaultValue: T) -> T {
switch(self) {
case .none:
return defaultValue
case .some(let value) where value.isEmpty:
return defaultValue
case .some(let value):
return value as! T
}
}
}
extension String: Emptyable {}
Now the question is: Is there a way I can get rid of the Emptyable protocol and instead have a conditional check whether or not a property or function is implemented by the generic type so that I automatically get orWhenNilOrEmpty() for each and every type which has isEmpty?
UPDATE
As suggested by Paulo, the T generic is actually not needed and I created a operator for even quicker access and more convenient usage (at least I think so. Feel free to correct me, I'm always happy to learn new things and improve myself).
I call it the "not empty nil coalescing" operator (who can come up with a better names? I feel like I suck at naming things :/ ). Hopefully some day it helps somebody:
protocol Emptyable {
var isEmpty: Bool { get }
}
infix operator ???: NilCoalescingPrecedence
extension Optional where Wrapped: Emptyable {
func orWhenNilOrEmpty(_ defaultValue: Wrapped) -> Wrapped {
switch(self) {
case .none:
return defaultValue
case .some(let value) where value.isEmpty:
return defaultValue
case .some(let value):
return value
}
}
static func ???(left: Wrapped?, right: Wrapped) -> Wrapped {
return left.orWhenNilOrEmpty(right)
}
}
extension String: Emptyable {}
extension Array: Emptyable {}
extension MyStruct: Emptyable {
let text: String
let number: Int
var isEmpty: Bool { return text.isEmpty && number == 0 }
init(text: String, number: Int) {
self.text = text
self.number = number
}
}
let mandatoryNotEmptyString = optionalOrEmptyString ??? "Default Value"
let mandatoryNotEmptyStruct = optionalOrEmptyStruct ??? MyStruct(name: "Hello World", number: 1)
No, you cannot query if an object or value has a certain property as a constraint on an extension without using a protocol. That would require reflection in a way that is currently not implemented in Swift. Also, an isEmpty property could have different meanings for different types, so testing for the existence of a method or property instead of a protocol could lead to unexpected behaviour.
You could just write
if let unwrappedString = optionalString, !unwrappedString.isEmpty {
// Do stuff
} else {
// Use default value
}
No protocol or extension required and very readable.
In Swift 4, which is coming out this fall, String will conform to BidirectionalCollection, which inherits from Collection. The Collection protocol provides an isEmpty property, so your extension could be
extension Optional where Wrapped: Collection {
// ...
}
But even then you should consider to set empty strings to nil when storing them in the first place, because you now have two states (nil and empty) which seem to represent the exact same thing.

Can not check equality of values of type T: Equatable inside a generic

I'm currently trying out with some basic data structures like LinkedList. I defined a ListNode class of generics values, like this:
class ListNode<T> {
var nodeContent: T
var nextNode: ListNode<T>? = nil
init() {
// details omitted here
}
And then a linked list. I want to implement the contains() method, so I have sth like this:
func contains<T>(_ item: T) -> Bool {
var currNode = self.head
while (currNode != nil) {
if currNode?.nodeContent == item {
return true
}
currNode = currNode?.nextNode
}
return false
}
Then it's giving me error saying that '==' cannot applied to T and T types. I then looked through the language guide and changed ListNode class and LinkedList struct to this:
class ListNode<T: Equatable>{}
struct LinkedList<T: Equatable>{}
But it's not working, so I added 'Equatable' to func itself:
func contains<T: Equatable>(_ item: T) -> Bool
Still fails. I tried pasting the sample function from the language guide inside,
func findIndex<T: Equatable>(of valueToFind: T, in array:[T]) -> Int? {
for (index, value) in array.enumerated() {
if value == valueToFind {
return index
}
}
return nil
}
No error occurs. May I know why it's like this? I tried searching, but all suggested answers like this doesn't clear my doubts. Thanks in advance!
You just don't need to make the contains method generic (twice). It's inside of your already generic class and knows about T type. It's right to require T: Equatable in the type declaration.
findIndex(of:in:) works as is, because it's not a method, but rather a standalone generic function.

Swift - Take Nil as Argument in Generic Function with Optional Argument

I am trying to create a generic function that can take an optional argument.
Here's what I have so far:
func somethingGeneric<T>(input: T?) {
if (input != nil) {
print(input!);
}
}
somethingGeneric("Hello, World!") // Hello, World!
somethingGeneric(nil) // Errors!
It works with a String as shown, but not with nil.
Using it with nil gives the following two errors:
error: cannot invoke 'somethingGeneric' with an argument list of type '(_?)'
note: expected an argument list of type '(T?)'
What am I doing wrong and how should I correctly declare/use this function? Also, I want to keep the usage of the function as simple as possible (I don't want do something like nil as String?).
I guess the compiler can't figure out what T is just from nil.
The following works just fine though for example:
somethingGeneric(Optional<String>.None)
I believe you've overcomplicated the problem by requiring the ability to pass untyped nil (which doesn't really exist; even nil has a type). While the approach in your answer seems to work, it allows for the creation of ?? types due to Optional promotion. You often get lucky and that works, but I've seen it blow up in really frustrating ways and the wrong function is called. The problem is that String can be implicitly promoted to String? and String? can be implicitly promoted to String??. When ?? shows up implicitly, confusion almost always follows.
As MartinR points out, your approach is not very intuitive about which version gets called. UnsafePointer is also NilLiteralConvertible. So it's tricky to reason about which function will be called. "Tricky to reason about" makes it a likely source of confusing bugs.
The only time your problem exists is when you pass a literal nil. As #Valentin notes, if you pass a variable that happens to be nil, there is no issue; you don't need a special case. Why force the caller to pass an untyped nil? Just have the caller pass nothing.
I'm assuming that somethingGeneric does something actually interesting in the case that it is passed nil. If that's not the case; if the code you're showing is indicative of the real function (i.e. everything is wrapping in an if (input != nil) check), then this is a non-issue. Just don't call somethingGeneric(nil); it's a provable no-op. Just delete the line of code. But I'll assume there's some "other work."
func somethingGeneric<T>(input: T?) {
somethingGeneric() // Call the base form
if (input != nil) {
print(input!);
}
}
func somethingGeneric() {
// Things you do either way
}
somethingGeneric(input: "Hello, World!") // Hello, World!
somethingGeneric() // Nothing
Good question and answer. I have an Swift 4 update to contribute:
var str: String? = "Hello, playground"
var list: Array<String>? = ["Hello", "Coder256"]
func somethingGeneric<T>(_ input: T?) {
if (input != nil) {
print(input!);
}
}
func somethingGeneric(_ input: ExpressibleByNilLiteral?) {}
somethingGeneric("Hello, World!") // Hello, World!
somethingGeneric(nil) // *nothing printed*
somethingGeneric(nil as String?) // *nothing printed*
somethingGeneric(str) // Hello, playground
str = nil
somethingGeneric(str) // *nothing printed*
somethingGeneric(list) // ["Hello", "Coder256"]
list = nil
somethingGeneric(list) // *nothing printed*
I figured it out:
func somethingGeneric<T>(input: T?) {
if (input != nil) {
print(input!);
}
}
func somethingGeneric(input: NilLiteralConvertible?) {}
somethingGeneric("Hello, World!") // Hello, World!
somethingGeneric(nil) // *nothing printed*
somethingGeneric(nil as String?) // *nothing printed*
I think that you will never call somethingGeneric(nil) but mostly somethingGeneric(value) or somethingGeneric(function()) for which the compiler has enough info not to be stucked trying to guess the type:
func somethingGeneric<T>(input: T?) {
if let input = input {
print(input);
}
}
func neverString() -> String? {
return nil
}
let a: String? = nil
somethingGeneric("Hello, World!") // Hello, World!
somethingGeneric(a) // Nothing and no error
somethingGeneric(neverString()) // Nothing and no error
Also, I would use the if let syntax instead of if(value != nil).
Here is the solution I came up with that compiles on Swift 5, as many of the solutions here did not compile for me. It might be considered hacky as I use a stored variable to help things along. I was unable to come up with a Swift 5 version of the nil parameters that resolve to type T.
class MyClass {
func somethingGeneric<T>(input: T?) {
if let input = input {
print(input)
}
}
func somethingGeneric() {
somethingGeneric(Object.Nil)
}
}
final class Object {
static var Nil: Object? //this should never be set
}
Actually there is a way to do this, inspired by Alamofire's internal code.
You do not have to install Alamofire to use this solution.
Usage
Your problematic method definition
func someMethod<SomeGenericOptionalCodableType: Codable>(with someParam: SomeGenericOptionalCodableType? = nil) {
// your awesome code goes here
}
What works ✅
// invoke `someMethod` correctly
let someGoodParam1 = Alamofire.Empty.value
someMethod(with: someGoodParam1)
I think it is possible to use Alamofire.Empty.value as a default value in someMethod definition as a parameter.
What does not work ❌
// invoke `someMethod` incorrectly
let someBadParam1: Codable? = nil
let someBadParam2 = nil
someMethod(with: someBadParam1)
someMethod(with: someBadParam2)
Solution definition (source)
/// Type representing an empty value. Use `Empty.value` to get the static instance.
public struct Empty: Codable {
/// Static `Empty` instance used for all `Empty` responses.
public static let value = Empty()
}

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

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.