检查多个字符串是否为空的优雅方式

5

如何优雅地检查多个字符串是否为空?这是我目前的做法:

//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

    }

4
我建议使用 http.StatusBadRequest 而不是自定义的变量/常量 UNABLE_TO_PROCEED。这样做有以下两个好处:1. 这是标准用法,更易于阅读(任何人阅读您的代码都会知道它的含义);2. 您的变量违反了 Go 语言的两个惯用法:变量名中不要使用下划线 _,并且不要全部使用大写字母。 - Jonathan Hall
1
另一种方法可能是添加一个名为 registerRequest 的方法来检查是否有任何必填字段为空。 - Mario Santini
3个回答

12

注意:如果在处理程序中保留“is-valid”条件,并将条件分离到另一个函数或方法中,您可以使用下面的解决方案。

您可以创建一个简单的帮助函数,它具有可变参数,并且您可以使用任意数量的string值调用它:

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

使用它的示例:

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.")
}

尝试在Go Playground上运行以上代码的输出结果为:

One is empty!
All is non-empty.

你的示例代码将会是这样的:

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

    // One of the listed strings is empty
}

此外,registerRequest有点长,可以缩短为r。如果您不能或不想在周围的代码中重命名它,并且想要缩短条件,则也可以这样做:

如果registerRequest是一个指针(或接口),您也可以这样写:

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

    // One of the listed strings is empty
}

即使 registerRequest 不是一个指针,你仍然可以这样做,但这时结构体将会被复制。如果 registerRequest 是一个 struct,那么你可以取它的地址来避免像这样复制它:

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

    // One of the listed strings is empty
}

1
糟糕的函数名hasZero,正确的名字应该是isNotEmpty (https://talks.golang.org/2014/names.slide#2),而registerRequest应该被重命名为r。但在if语句中不要使用别名,应该在整个函数中进行重命名。 - lofcek
@lofcek isNotEmpty 是一个很好的集合名称,用于检查其大小是否大于0。hasZero() 则用于判断传递值列表中是否存在零值(即与其类型的零值相等的值)。关于 registerRequest:我同意。 - icza
虽然我同意在 string 值的情况下,containsEmpty() 更直观。已经更新了答案。 - icza

5

正如Mario Santini在评论中提到的那样,为了增加可测试性、封装这些逻辑并将其与处理器方法解耦(根据字段数量来判断它的变化速度可能会与处理器不同步),一种方法是将这些逻辑放入一个函数中:

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

现在支持非常专注的基于表格驱动的测试,可以独立于涉及编写标头的任何方法来测试有效请求的含义。

它允许您验证封闭函数的有效/无效路径,但在此处进行非常专注的测试。 它还允许您更改有效请求的含义并独立验证它,而不受封闭函数的影响。


1
你可以使用 switch
switch "" {
case registerRequest.Email,
registerRequest.NachName,
registerRequest.Password,
registerRequest.PhoneNumber,
registerRequest.VerificationId,
registerRequest.VorName:
   w.WriteHeader(UNABLE_TO_PROCEED)
   w.Write([]byte("Unable to register account."))
   return
}

https://golang.org/ref/spec#Switch_statements


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接