Go If流程控制与快乐路径原则

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 if(N)分支结构(if ... else if ... else)
    • 四、if 语句的自用变量
    • 五、if 语句的“快乐路径”原则

一、流程控制基本介绍

流程控制是每种编程语言控制逻辑走向和执行次序的重要部分,流程控制可以说是一门语言的“经脉”。

那么 Go 语言对分支与循环两种控制结构的支持是怎么样的呢?针对程序的分支结构,Go 提供了 ifswitch-case 两种语句形式;我们就先从 Go 语言分支结构之一的 if 语句开始讲起。

二、if 语句

2.1 if 语句介绍

if 语句是 Go 语言中提供的一种分支控制结构,它也是 Go 中最常用、最简单的分支控制结构。它会根据布尔表达式的值,在两个分支中选择一个执行。

2.2 单分支结构的 if 语句形式

单分支结构的if语句包含一个条件表达式和一个要执行的代码块。如果条件表达式的值为true,则执行代码块。如果条件表达式的值为false,则代码块将被跳过。以下是单分支结构的if语句的一般形式:

if boolean_expression {// 新分支
}// 原分支

这个 if 语句中的代码执行流程就等价于下面这幅流程图:

  • boolean_expression是一个布尔表达式,通常返回truefalse
  • 如果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:当ab都为true时,该表达式的求值 结果为true
``
``逻辑非

3.2 操作符的优先级

一元操作符,比如上面的逻辑非操作符,具有最高优先级,其他操作符的优先级如下:

优先级(从高到低)操作符列表
5*, /, %, <<, >>, &, &^
4+, -
3!=, ==, <, <=, >, >=
2&&
1||
  • 优先级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 if(N)分支结构(if … else if … else)

if条件(N)分支结构格式如下:

if boolean_expression1 {// 分支1
} else if boolean_expression2 {// 分支2... ...} else if boolean_expressionN {// 分支N
} else {// 分支N+1
}

以下面是一个四分支的wei伪代码示例:

if boolean_expression1 {// 分支1
} else if boolean_expression2 {// 分支2
} else if boolean_expression3 {// 分支3
} else {// 分支4
} 

以下是一个示例,演示如何使用if-else结构来判断一个分数的等级:

package mainimport "fmt"func 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:

//伪代码段1:func 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:

// 伪代码段2:func 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 分支中的代码析出到一个函数中,再对原函数实施“快乐路径”原则。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/157318.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【CANN训练营】Ascend算子开发入门笔记

基础概念 什么是Ascend C Ascend C是CANN针对算子开发场景推出的编程语言,原生支持C和C标准规范&#xff0c;最大化匹配用户开发习惯&#xff1b;通过多层接口抽象、自动并行计算、孪生调试等关键技术&#xff0c;极大提高算子开发效率&#xff0c;助力AI开发者低成本完成算子…

Caffeine Cache

Caffeine Cache 高性能的 Java本地缓存库 底层使用 ConcurrentHashMap TinyLFU 一个近乎最佳的命中率 LRU&#xff1a;最近最少使用算法&#xff0c;每次访问数据都会将其放在我们的队尾&#xff0c;如果需要淘汰数据&#xff0c;就只需要淘汰队首即可。容易导致了热点数据…

Flink(林子雨慕课课程)

文章目录 12.Flink12.1 Flink简介12.2 为什么要选择Flink12.3 Flink应用场景12.4 Flink技术栈、体系架构和编程模型12.5 Flink的安装和编程实战 12.Flink 12.1 Flink简介 企业的处理架构已经由传统数据处理架构和大数据Lamda架构向流处理架构演变 Flink实现了Goole Dataflow…

AP5125 DC-DC降压恒流IC SOT23-6 过认证 9-100V 6A电源驱动线路图

1,产品描述 AP5125 是一款外围电路简单的 Buck 型平均电 流检测模式的 LED 恒流驱动器&#xff0c;适用于 8-100V 电压 范围的非隔离式大功率恒流 LED 驱动领域。芯片采用 固定频率 140kHz 的 PWM 工作模式&#xff0c; 利用平均电 流检测模式&#xff0c;因此具有优异的负载…

MySQL 3 环境搭建 MySQL 5.7版本的安装、配置

MySQL5.7.43官网下载地址 MySQL :: Download MySQL Community Server 这里选5.7.43&#xff0c;Windows版本&#xff0c;然后点击Go to Download Page&#xff0c;下载msi安装包的版本 MSI安装包版本比ZIP压缩包版本的安装过程要简单的多&#xff0c;过程更加清楚直观&#x…

十三、【画笔工具组】

文章目录 画笔工具铅笔工具颜色替换工具混合器画笔工具 画笔工具跟混合器画笔工具&#xff0c;是我们平时使用频率较高的两款工具: 画笔工具 可以把画笔工具看成我们用的毛笔,使用时可以在拾色器里边选择我们需要的画笔颜色,可以把拾色器当做我们画画时用的一个颜料盘&#xf…

数字IC/FPGA面试题目合集解析(一)

数字IC/FPGA面试题目合集解析&#xff08;一&#xff09; 题目概述题目1&#xff0c;计算题2&#xff0c;计算题3&#xff0c;选择题 答案与解析1&#xff0c;计算题2&#xff0c;计算题3&#xff0c;选择题 题目概述 1&#xff0c;计算题&#xff1a;计算该触发器等效的建立保…

怎样制作一个展会场馆预约小程序

随着互联网的发展&#xff0c;展会行业也逐渐向数字化转型。展会场馆预约小程序作为展会线下向线上的延伸&#xff0c;能够让参展商和观众随时随地进行预约&#xff0c;大大提升了客户的体验。那么&#xff0c;如何制作一个展会场馆预约小程序呢&#xff1f;下面就以乔拓云平台…

记录--纯CSS实现骚气红丝带

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 在本文中&#xff0c;我们将探讨如何使用 CSS 以最少的代码创造出精美的 CSS 丝带形状,并最终实现下面这个效果&#xff1a; 下面我们使用html和css来实现这个效果。我们使用内容自适应方式布局&#…

Redis分布式锁最牛逼的实现(Java 版,最牛逼的实现方式)

写在前面的话 分布式锁一般有三种实现方式&#xff1a;1. 数据库乐观锁&#xff1b;2. 基于Redis的分布式锁&#xff1b;3. 基于ZooKeeper的分布式锁。 本篇博客将介绍第二种方式&#xff0c;基于Redis实现分布式锁。 为什么需要分布式锁&#xff1f; 在单机环境下编写多线…

java中的泛型

一 为啥要有泛型 泛型这个概念是在Java1.5提出来的&#xff0c;之前是没有的&#xff0c;那为什么之前没有&#xff0c;现在要提出来这个概念呢&#xff1f;那你就得想啊&#xff1a; 1、要么是之前的技术太垃圾了&#xff0c;得升级换代下 2、要么是技术发展&#xff0c;搞出…

【数据结构】算法的空间复杂度

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 算法空间复杂度的定义 算法的时间复杂度和空间复杂度是度量算法好坏的两个重要量度,在实际写代码的过程中,我们完全可以用空间来换时间,比如说,我们要判断某某年是不是闰年,大…

github创建个人网页登录后404无法显示的问题

1.首先必须要有内容&#xff0c;默认是会找index.html文件&#xff0c;找不到该文件会找readme.md文件&#xff0c;也就是说最简单的方法是&#xff0c;创建了与用户名同名的repository后username.github.io后&#xff0c;添加一个readme.md文件&#xff0c;得在readme里打点字…

【算法-动态规划】最长上升子序列-力扣 300

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

设计模式-相关内容

文章目录 一、设计模式概述二、UML图1.类的表示方法2.类与类之间关系的表示方法(1)关联关系(2)聚合关系(3)组合关系(4)依赖关系(5)继承关系(6)实现关系 三、软件设计原则1.开闭原则2.里氏代换原则3.依赖倒转原则4.接口隔离原则5.合成复用原则6.迪米特法则 一、设计模式概述 创…

驾驶数字未来:汽车业界数字孪生技术的崭新前景

随着数字化时代的到来&#xff0c;汽车行业正经历着前所未有的变革。数字孪生技术&#xff0c;作为一种前沿的数字化工具&#xff0c;正在为汽车行业带来革命性的影响&#xff0c;不仅改变着汽车制造和维护的方式&#xff0c;也为消费者带来了前所未有的体验。让我们一起探讨&a…

[sqoop]hive导入mysql,其中mysql的列存在默认值列

一、思路 直接在hive表中去掉有默认值的了列&#xff0c;在sqoop导入时,指定非默认值列即可&#xff0c; 二、具体 mysql的表 hive的表 create table dwd.dwd_hk_rcp_literature(id string,literature_no string,authors string,article_title string,source_title string…

OLED透明拼接屏:福州鼓山风景区:徜徉于城市壮丽之

福州是中国福建省的省会城市&#xff0c;历史悠久&#xff0c;文化底蕴深厚。 该城市曾是唐宋时期的重要港口城市&#xff0c;也是丝绸之路海上丝绸之路的起点之一。 福州以其独特的地理位置和丰富的历史遗产而闻名于世。 福州拥有众多的历史景点&#xff0c;其中最著名的是…

MySQL为什么用b+树

索引是一种数据结构&#xff0c;用于帮助我们在大量数据中快速定位到我们想要查找的数据。 索引最形象的比喻就是图书的目录了。注意这里的大量&#xff0c;数据量大了索引才显得有意义&#xff0c;如果我想要在[1,2,3,4]中找到4这个数据&#xff0c;直接对全数据检索也很快&am…

动态盘转换为基本盘

问题描述 不小心将磁盘0&#xff08;C和D是基本盘&#xff0c;蓝颜色&#xff09;改成了动态盘&#xff08;C和D是动态盘&#xff0c;橘黄色&#xff09;&#xff1f;如何修改回来呢&#xff1f; 解决方案&#xff1a; 使用DiskGenius将动态磁盘转换为基本磁盘 操作之前一定…