20210311关于逻辑运算符的执行规则 - ziyouzy/2021blog GitHub Wiki

遇到了一个很好的例子:

river.usr-io808的func (p *USR_IO808) attachRiverNode(riverNodeName string, config rn.Config)bool函数:
for _, riverNode := range p.riverNodes {
    if riverNode.Name == riverNodeName {
        p.Errors <- NewError(RIVER_USRIO808_INITFAIL, p.UniqueId, 
                 fmt.Sprintf("river-node:%s已被装载与当前river,导致了uid为%s的usr-io8080设备"+
                    "初始化失败", riverNodeName, p.UniqueId))
        return false
    }
}

以及river.byteslice的func (p *ByteSlice) attachRiverNode(riverNodeName string, config rn.Config)bool函数
if p.crc_addTail != nil && p.crc_addTail.Name == riverNodeName {
// if p.crc_addTail.Name == riverNodeName { 报错
    p.Errors <- NewError(RIVER_BYTESLICEASKER_INITFAIL, p.UniqueId, 
             fmt.Sprintf("river-node:%s已被装载与当前river,导致了uid为%s"+
                "的bytesliceasker设备初始化失败", riverNodeName, p.UniqueId))
    return false
}

前者由于for range结构,使得程序会先进行一次数组的range操作,如果内部字段p.riverNodes为空则不会执行循环的内部逻辑,从而避免了调用一个空值的Name()方法
后者由于没有for range的保护于是直接触发了panic

接下来介绍重点,如先进性一次如下书写格式的非空的判断if p.crc_addTail != nil && p.crc_addTail.Name == riverNodeName程序就不会触发panic
因此得出结论虽然上面是一条语句,但是其具备两条语句的特性,如果第一个条件就判定失败则不会进行接下来的操作,一直了解这个很棒的设计,而在这里遇到了最好的实践场景