How to handle missing variable panic properly?

I have the following simple go-lang code.

aud := claims["aud"].(string)

It's a jwt claim so it always exist. Then I was trying to experiment on changing the variable from aud to missing-aud.

When I changed it, then tested. I noticed a critical panic.

[PANIC RECOVER] interface conversion: interface {} is nil, not string goroutine 7

What is the simplest way to handle a missing variable and not panic?

I have tried, but it seems not the case.

var aud string
    if claims["audx"].(string) != "" {
        aud = claims["audx"].(string)
    }

Thanks for anyone who could help


Modified with an answer, but was looking if this could be simplified?

    var aud string
    if _, found := claims["audx"].(string); found {
        aud = claims["audx"].(string)
    }

2 answers

  • answered 2020-10-23 13:11 colm.anseo

    As @JimB pointed out - you are confusing type assertion (claims["audx"].(string)) with a map-key existence check (v, ok := claims["audx"]):

    If your map value is of type interface{} - then yes you need type assertion. But you also want a key check before you check the value e.g.

    if v, ok := claims["audx"]; ok {
    
            log.Printf("audx key exists")
    
            if vs, ok := v.(string); ok {
                // "audx" value is a string
                aud = vs
                log.Printf("audx value is a string: %q", aud)
            }
    
    }
    

    This playground example should make it clearer: https://play.golang.org/p/pTOR39wDCx5

  • answered 2020-10-23 13:13 JimB

    The form of your if statement is valid, and would work here, but the found value is not what you are expecting. It is the result of the type assertion, rather than the map index.

    _, found := claims["audx"].(string)
    

    can be broken down as

    v := claims["audx"]
    _, ok := v.(string)
    

    Since the zero value for the type assertion is valid for your purpose, and you are taking no action on the result of the index or assertion conditionals, you can simplify the expression to:

    audx, _ := claims["audx"].(string)
    

    This works because if the map returns nil, the type assertion simply fails, but will give you the zero value of that type.