4

I recently started learning golang and Revel. Im trying to understand what exactly the below if statement does. Seems like it is doing a type check, but i dont see what the conditional achieves. Appreciate if anyone can tell me whats happening here. thanks

if str, ok := obj.(string); ok {
return len(str) > 0
}
broun
  • 2,483
  • 5
  • 40
  • 55

2 Answers2

6

It tries to convert obj (which is of some abstract interface probably) into a string, checks if that worked, and only enters if it turned out okay.

Written more sparsely it can be viewed as:

// do a type assertion/conversion of obj to a string. 
// If obj isn't really a string, ok will be false
str, ok := obj.(string) 

// this will only run if we're talking about a string
if ok {
 return len(str) > 0
}

What go does is safe casting from some interface to the real type. If you do this without the ok part, your program will panic if obj isn't a string. i.e this code will crash your program if obj isn't a string:

str := obj.(string) 
return len(str) > 0   

You can read more about type assertions in the docs:

http://golang.org/ref/spec#Type_assertions

Not_a_Golfer
  • 47,012
  • 14
  • 126
  • 92
3

This is called a type assertion. Your variable obj is an interface{}, in other words, its real type can change from one execution to another. A type assertion is used to determine the real type of an interface{}. There are two ways to do so:

str = obj.(string)

This one is unsecure: if ever obj is not a string, the program will panic. The other one is the one you used in your code. If obj is not a string, the ok boolean will be false.

For instance:

func f(v interface{}) {
    if _, ok := v.(string); ok {
        fmt.Println("v is a string!")
    } else if _, ok := v.(float64); ok {
        fmt.Println("v is a float64!")
    } else {
         fmt.Println("v is something else...")
    }
}
f(17.42) // "v is a float64!"
f("foobar") // "v is a string!"
f([]string{"hello", "world"}) // "v is something else..."
julienc
  • 19,087
  • 17
  • 82
  • 82
  • `[]interface{}` should be replaced with `interface{}`. `str` and `if` should be used eg. `fmt.Println(str)` and `fmt.Println(if)`. –  Apr 24 '20 at 01:05