受if子句

时间:2018-10-11 12:15:53

标签: go

我遇到一个if语句遇到麻烦,该语句包括一个if子句的前面语句部分的条件。

在这个简化的示例中,我想将ID扩展为按名称查找,也将名称扩展为首选前缀。

伪代码为:

IF I have a prefix AND I can find a record using the prefix and name
THEN override the record ID
ELSE IF I can find a record using name
THEN override the record ID
ELSE do something else to override the record ID

在bash中很简单:

if test -n "$PREFIX" && id_=$(GetByName "$PREFIX:$id")
then id="$id_"
elif id_=$(GetByName "$id")
then id="$id_"
elif id_=$(legacy_attempt "$id")
then id="$id_"
fi

但是如何表达呢?

这是错误的:

if PREFIX != "" && n, err := GetByName(PREFIX + ":" + id) && err == nil {
    id = n.ID
} else if n, err := GetByName(id) && err == nil {
    id = n.ID
} else if n, err := legacy_attempt(id) && err == nil {
    id = n
}

我正在猜测,因为&&序列的中间部分是语句,而不是表达式(与C不同)。

我尝试使用=而不是:=,并且将errg声明为超出范围,但这无济于事。

我尝试过以下恐怖活动:

if if PREFIX != "" { n, err := GetByName(PREFIX + ":" + id) } ; err == nil {

但是该错误比nerr的作用域范围错误大, go 声称尽管我在if之后仍希望有表达式试图给它一个由if组成的前面的语句

由于PREFIX上的前导条件为非空,因此我无法轻易地将此if条件转换为使用前面的语句。如果上半部分不执行或上半部失败,我希望下半部分执行。

这里有有用的 go 惯用语吗?

我可以将代码分解为与sin *一样丑陋,带有重复的块,但是我正在寻找一个很好的惯用答案。

*我的意思是丑陋的,因为有两个else if子句。

2 个答案:

答案 0 :(得分:2)

更清洁的解决方案是定义一个辅助函数:

func getId(prefix string, name string) (int, error) {
    if (prefix != "") {
        if n, err := GetByName(prefix + ":" + name); err == nil {
            return n.ID, nil
        }
    }
    return GetByName(name)
}

并调用该函数:

if newId, err := getId(prefix, name) {
   id = newId
}

答案 1 :(得分:1)

您不能使用单个if语句来执行此操作,因此请使用其中两个。并且您可以使用“状态”变量来跟踪第一次查找是否成功:

found := false
if PREFIX != "" {
    if n, err := GetByName(PREFIX + ":" + id); err == nil {
        id, found  = n.ID, true
    }
}
if !found {
    if n, err := GetByName(id); err == nil {
        id = n.ID
    }
}

如果创建辅助功能,则可以使原始任务更加紧凑。对该实用程序功能进行映像:

func lookup(name string, id *string) (ok bool) {
    if n, err := GetByName(name); err == nil {
        *id = n.ID
        return true
    }
    return false
}

有了这个,您的原始任务将是:

_ = PREFIX != "" && lookup(PREFIX+":"+id, &id) || lookup(id, &id)

上一行的正确性基于布尔逻辑的短路评估。也就是说,如果PREFIX为非空且第一次查找成功,则不会调用第二次查找。如果PREFIX为空或第一次查找“失败”,则将调用第二次查找。

尽管第二个版本非常紧凑,但我仍然会选择第一个更详细但更干净的解决方案。最终,您的目标不是编写最紧凑的代码,而是编写最易读,最易维护的代码。