Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elegant way to check if multiple strings are empty

How can I check if multiple strings are empty in an elegant way? This is how I currently do it:

//if one required field is empty, close the connection
    if (registerRequest.Email == "") ||
        (registerRequest.PhoneNumber == "")||
        (registerRequest.NachName =="") ||
        (registerRequest.VorName =="") ||
        (registerRequest.Password =="") ||
        (registerRequest.VerificationId ==""){

        //Could not proceed
        w.WriteHeader(UNABLE_TO_PROCEED)
        w.Write([]byte("Unable to register account."))
        return

    }
like image 290
thelearner Avatar asked Jan 12 '18 12:01

thelearner


2 Answers

Note: You may use the solution below if you keep the "is-valid" condition in your handler, and also if you separate your condition into another function or method.

You can create a simple helper function, which has a variadic parameter, and you can call it with any number of string values:

func containsEmpty(ss ...string) bool {
    for _, s := range ss {
        if s == "" {
            return true
        }
    }
    return false
}

Example using it:

if containsEmpty("one", "two", "") {
    fmt.Println("One is empty!")
} else {
    fmt.Println("All is non-empty.")
}

if containsEmpty("one", "two", "three") {
    fmt.Println("One is empty!")
} else {
    fmt.Println("All is non-empty.")
}

Output of the above (try it on the Go Playground):

One is empty!
All is non-empty.

Your example would look like this:

if containsEmpty(registerRequest.Email,
    registerRequest.PhoneNumber,
    registerRequest.NachName,
    registerRequest.VorName,
    registerRequest.Password,
    registerRequest.VerificationId) {

    // One of the listed strings is empty
}

Also registerRequest is a kinda long name, it could be shortened to like r. If you can't or don't want to rename it in the surrounding code and if you want to shorten the condition, you could also do something like this:

If registerRequest is a pointer (or interface), you could also write:

if r := registerRequest; containsEmpty(r.Email,
    r.PhoneNumber,
    r.NachName,
    r.VorName,
    r.Password,
    r.VerificationId) {

    // One of the listed strings is empty
}

Actually you can do this even if registerRequest is not a pointer, but then the struct will be copied. If registerRequest is a struct, then you can take its address to avoid having to copy it like this:

if r := &registerRequest; containsEmpty(r.Email,
    r.PhoneNumber,
    r.NachName,
    r.VorName,
    r.Password,
    r.VerificationId) {

    // One of the listed strings is empty
}
like image 84
icza Avatar answered Nov 15 '22 07:11

icza


As Mario Santini mentioned in comment, a way to increase testability, encapsulate this logic, and decouple it from your handler method (which judging by the number of fields looks like it is at risk of changing at a different rate than your handler) could be to put this logic in a function:

func validRequest(registerRequest ?) bool {
   return registerRequest.Email == "" ||
        registerRequest.PhoneNumber == "" ||
        registerRequest.NachName == "" ||
        registerRequest.VorName == "" ||
        registerRequest.Password == "" ||
        registerRequest.VerificationId == ""
}

This now supports very focused, table driven tests, that can exercise what it means to be a valid request independent of any method involving writing headers.

It allows you to verify the valid/invalid path of your enclosing function, but to have very focused tests here. It also allows you to change what it means to be a valid request and verify it independent of your enclosing function.

like image 39
dm03514 Avatar answered Nov 15 '22 05:11

dm03514