临沂手机建站模板,正规代加工项目,平台推广是什么,做淘客网站的公司Go if流程控制与快乐路径原则 文章目录 Go if流程控制与快乐路径原则一、流程控制基本介绍二、if 语句2.1 if 语句介绍2.2 单分支结构的 if 语句形式2.3 Go 的 if 语句的特点2.3.1 分支代码块左大括号与if同行2.3.2 条件表达式不需要括号 三、操作符3.1 逻辑操作符3.2 操作符的…Go if流程控制与快乐路径原则 文章目录 Go if流程控制与快乐路径原则一、流程控制基本介绍二、if 语句2.1 if 语句介绍2.2 单分支结构的 if 语句形式2.3 Go 的 if 语句的特点2.3.1 分支代码块左大括号与if同行2.3.2 条件表达式不需要括号 三、操作符3.1 逻辑操作符3.2 操作符的优先级 三、if 多N分支结构3.1 if else(分支结构)3.2 ifN分支结构(if ... else if ... else) 四、if 语句的自用变量五、if 语句的“快乐路径”原则 一、流程控制基本介绍
流程控制是每种编程语言控制逻辑走向和执行次序的重要部分流程控制可以说是一门语言的“经脉”。
那么 Go 语言对分支与循环两种控制结构的支持是怎么样的呢针对程序的分支结构Go 提供了 if 和 switch-case 两种语句形式我们就先从 Go 语言分支结构之一的 if 语句开始讲起。
二、if 语句
2.1 if 语句介绍
if 语句是 Go 语言中提供的一种分支控制结构它也是 Go 中最常用、最简单的分支控制结构。它会根据布尔表达式的值在两个分支中选择一个执行。
2.2 单分支结构的 if 语句形式
单分支结构的if语句包含一个条件表达式和一个要执行的代码块。如果条件表达式的值为true则执行代码块。如果条件表达式的值为false则代码块将被跳过。以下是单分支结构的if语句的一般形式
if boolean_expression {// 新分支
}// 原分支这个 if 语句中的代码执行流程就等价于下面这幅流程图 boolean_expression是一个布尔表达式通常返回true或false。如果boolean_expression的值为true则执行// 当条件为真时执行的代码部分的代码块。如果boolean_expression的值为false则代码块将被跳过继续执行下一个语句。
2.3 Go 的 if 语句的特点
2.3.1 分支代码块左大括号与if同行
if 语句的分支代码块的左大括号与 if 关键字在同一行上这是 Go 代码风格的统一要求gofmt 工具会帮助我们实现这一点
2.3.2 条件表达式不需要括号
if 语句的布尔表达式整体不需要用括号包裹这使得代码更加简洁。而且if 关键字后面的条件判断表达式的求值结果必须是布尔类型即要么是 true要么是 false
if runtime.GOOS darwin {println(we are on MacOS)
}如果判断的条件比较多我们可以用多个逻辑操作符连接起多个条件判断表达式比如这段代码就是用了多个逻辑操作符 来连接多个布尔表达式 if (runtime.GOOS darwin) (runtime.GOARCH amd64) (runtime.Compiler ! gccgo) {println(we are using standard go compiler on Mac os for amd64)}上面示例代码中的每个布尔表达式都被小括号括上了这是为了降低你在阅读和理解这段代码时面对操作符优先级的心智负担。
三、操作符
3.1 逻辑操作符
逻辑操作符除了上面的 之外Go 还提供了另外两个逻辑操作符如下表
逻辑操作符含义表达式求值举例逻辑与a b:当a和b都为true时,该表达式的求值 结果为true逻辑非
3.2 操作符的优先级
一元操作符比如上面的逻辑非操作符具有最高优先级其他操作符的优先级如下
优先级(从高到低)操作符列表5*, /, %, , , , ^4, -3!, , , , , 21||
优先级5的是乘、除、取模和位操作符优先级4的是加法和减法运算符优先级3的是关系和相等运算符优先级2的是逻辑与优先级最低的是逻辑或
操作符优先级决定了操作数优先参与哪个操作符的求值运算我们以下面代码中 if 语句的布尔表达式为例
func main() {a, b : false,trueif a b ! true {println((a b) ! true)return}println(a (b ! true) false)
}这段代码会输出得到的是 a (b ! true) false。这是为什么呢
这段代码的关键就在于if 后面的布尔表达式中的操作数 b 是先参与 的求值运算还是先参与! 的求值运算。根据前面的操作符优先级表我们知道! 的优先级要高于 因此操作数 b 先参与的是! 的求值运算这样 if 后的布尔表达式就等价于 a (b ! true) 。
针对以上问题推荐在 if 布尔表达式中使用带有小括号的子布尔表达式来清晰地表达判断条件。
这样做不仅可以消除了自己记住操作符优先级的学习负担当其他人阅读你的代码时也可以很清晰地看出布尔表达式要表达的逻辑关系这能让我们代码的可读性更好更易于理解不会因记错操作符优先级顺序而产生错误的理解。
三、if 多N分支结构
3.1 if else(分支结构)
Go语言中if else(分支结构)条件判断的格式如下
if boolean_expression {// 分支1
} else {// 分支2
}3.2 ifN分支结构(if … else if … else)
if条件N分支结构格式如下
if boolean_expression1 {// 分支1
} else if boolean_expression2 {// 分支2... ...} else if boolean_expressionN {// 分支N
} else {// 分支N1
}以下面是一个四分支的wei伪代码示例
if boolean_expression1 {// 分支1
} else if boolean_expression2 {// 分支2
} else if boolean_expression3 {// 分支3
} else {// 分支4
} 以下是一个示例演示如何使用if-else结构来判断一个分数的等级
package mainimport fmtfunc main() {score : 85if score 90 {fmt.Println(A)} else if score 80 {fmt.Println(B)} else if score 70 {fmt.Println(C)} else {fmt.Println(D)}
}四、if 语句的自用变量
无论是单分支、二分支还是多分支结构我们都可以在 if 后的布尔表达式前进行一些变量的声明在 if 布尔表达式前声明的变量叫 if 语句的自用变量。顾名思义这些变量只可以在 if 语句的代码块范围内使用比如下面代码中的变量 a、b 和 c
func main() {if a, c : f(), h(); a 0 {println(a)} else if b : f(); b 0 {println(a, b)} else {println(a, b, c)}
}我们可以看到自用变量声明的位置是在每个 if 语句的后面布尔表达式的前面而且由于声明本身是一个语句所以我们需要把它和后面的布尔表达式通过分号分隔开。
在 if 语句中声明自用变量是 Go 语言的一个惯用法这种使用方式直观上可以让开发者有一种代码行数减少的感觉提高可读性。同时由于这些变量是 if 语句自用变量它的作用域仅限于 if 语句的各层隐式代码块中if 语句外部无法访问和更改这些变量这就让这些变量具有一定隔离性这样你在阅读和理解 if 语句的代码时也可以更聚焦。
五、if 语句的“快乐路径”原则
上面我们已经学了 if 分支控制结构的三种形式了从可读性上来看单分支结构要优于二分支结构二分支结构又优于多分支结构。那么显然我们在日常编码中要减少多分支结构甚至是二分支结构的使用这会有助于我们编写出优雅、简洁、易读易维护且不易错的代码。
首先,我们来看一段伪代码段1:
//伪代码段1func doSomething() error {if errorCondition1 {// some error logic... ...return err1}// some success logic... ...if errorCondition2 {// some error logic... ...return err2}// some success logic... ...return nil
}
我们看到单分支控制结构的伪代码段 1 有这几个特点
没有使用 else 分支失败就立即返回“成功”逻辑始终“居左”并延续到函数结尾没有被嵌入到 if 的布尔表达式为 true 的代码分支中整个代码段布局扁平没有深度的缩进代码的可读性很高
我们来看一段伪代码段2:
// 伪代码段2func doSomething() error {if successCondition1 {// some success logic... ...if successCondition2 {// some success logic... ...return nil} else {// some error logic... ...return err2}} else {// some error logic... ...return err1}
}伪代码段 2 实现了同样逻辑码段 1就使用了带有嵌套的二分支结构它的特点如下
整个代码段呈现为“锯齿状”有深度缩进“成功”逻辑被嵌入到 if 的布尔表达式为 true 的代码分支中
很明显伪代码段 1 的逻辑更容易理解也更简洁。Go 社区把这种 if 语句的使用方式称为 if 语句的“快乐路径Happy Path”原则所谓“快乐路径”也就是成功逻辑的代码执行路径它的特点是这样的 仅使用单分支控制结构 当布尔表达式求值为 false 时也就是出现错误时在单分支中快速返回 正常逻辑在代码布局上始终“靠左”这样读者可以从上到下一眼看到该函数正常逻辑的全貌 函数执行到最后一行代表一种成功状态。
Go 社区推荐 Gopher 们在使用 if 语句时尽量符合这些原则如果你的函数实现代码不符合“快乐路径”原则你可以按下面步骤进行重构 尝试将“正常逻辑”提取出来放到“快乐路径”中 如果无法做到上一点很可能是函数内的逻辑过于复杂可以将深度缩进到 else 分支中的代码析出到一个函数中再对原函数实施“快乐路径”原则。