Go后端开发 -- 条件、循环语句 defer语句

Go后端开发 – 条件、循环语句 && defer语句

文章目录

  • Go后端开发 -- 条件、循环语句 && defer语句
  • 一、条件语句
    • 1.if ... else 语句
    • 2.switch语句
    • 3.select语句
  • 二、循环语句
    • 1.for循环
  • 三、defer语句
    • 1.defer语句的作用
    • 2.defer和return的先后顺序
    • 3.recover错误拦截


一、条件语句

1.if … else 语句

语法:

if 布尔表达式 {/* 在布尔表达式为 true 时执行 */
} else {/* 在布尔表达式为 false 时执行 */
}

与C的if … else语句的区别是条件不用加括号
实例

package mainimport "fmt"func main() {/* 局部变量定义 */var a int = 100;/* 判断布尔表达式 */if a < 20 {/* 如果条件为 true 则执行以下语句 */fmt.Printf("a 小于 20\n" );} else {/* 如果条件为 false 则执行以下语句 */fmt.Printf("a 不小于 20\n" );}fmt.Printf("a 的值为 : %d\n", a);
}

2.switch语句

语法:

switch var1 {case val1:...case val2:...default:...
}
  • switch 语句执行的过程从上至下,直到找到匹配项,匹配项后面也不需要再加 break
  • switch 默认情况下 case 最后自带 break 语句,匹配成功后就不会执行其他 case,如果我们需要执行后面的 case,可以使用 fallthrough
  • 变量 var1 可以是任何类型,而 val1 和 val2 则可以是同类型的任意值。类型不被局限于常量或整数,但必须是相同的类型;或者最终结果为相同类型的表达式
  • 可以同时测试多个可能符合条件的值,使用逗号分割它们,例如:case val1, val2, val3
  • switch语句可以不在switch开头确定判断的条件,可以在case中进行条件判断;

实例:

package Switchimport "fmt"func Switch() {grade := 'B'marks := 90switch marks {case 90:grade = 'A'case 80:grade = 'B'case 70, 60, 50:grade = 'C'default:grade = 'D'}switch {case grade == 'A':fmt.Println("优秀")case grade == 'B':fmt.Println("良好")case grade == 'C':fmt.Println("及格")default:fmt.Println("不及格")}fmt.Println("你的等级是:", grade)
}

在这里插入图片描述

  • switch语句还可以被用于type-switch来判断某个 interface 变量中实际存储的变量类型。

Type Switch 语法格式如下

switch x.(type){case type:statement(s);      case type:statement(s); /* 你可以定义任意个数的case */default: /* 可选 */statement(s);
}

实例:

package Switchimport "fmt"func TypeSwitch() {var x interface{}switch i := x.(type) {case nil:fmt.Printf("x的类型: %T\n", i)case int:fmt.Println("x是int型")case float64:fmt.Println("x是float64型")case func(int) float64:fmt.Println("x是func(int)型")case bool, string:fmt.Println("x是bool或string型")default:fmt.Println("未知型")}
}

在这里插入图片描述

  • fallthrough
    使用 fallthrough 会强制执行后面的 case 语句,包括defaultfallthrough 不会判断下一条case的表达式结果是否为 true。
  • fallthrough只会强制执行后面一条case语句,而不是后面的全部;

实例1:

package Switchimport "fmt"func Fallthrough() {switch {case false:fmt.Println("1.case条件语句为false")fallthroughcase true:fmt.Println("2.case条件语句为true")fallthroughcase false:fmt.Println("3.case条件语句为false")fallthroughcase true:fmt.Println("4.case条件语句为true")fallthroughcase false:fmt.Println("5.case条件语句为false")fallthroughdefault:fmt.Println("6.默认case")}
}

在这里插入图片描述
实例2:

package Switchimport "fmt"func Fallthrough() {switch {case false:fmt.Println("1.case条件语句为false")fallthroughcase true:fmt.Println("2.case条件语句为true")fallthroughcase false:fmt.Println("3.case条件语句为false")//fallthroughcase true:fmt.Println("4.case条件语句为true")//fallthroughcase false:fmt.Println("5.case条件语句为false")//fallthroughdefault:fmt.Println("6.默认case")}
}

在这里插入图片描述

3.select语句

select 是 Go 中的一个控制结构,类似于 switch 语句。

  • select 语句只能用于通道操作每个 case 必须是一个通道操作,要么是发送要么是接收。
  • select 语句会监听所有指定的通道上的操作,一旦其中一个通道准备好就会执行相应的代码块。
  • 如果多个通道都准备好,那么 select 语句会随机选择一个通道执行。如果所有通道都没有准备好,那么执行 default 块中的代码。

Go 编程语言中 select 语句的语法如下:

select {case <- channel1:// 执行的代码case value := <- channel2:// 执行的代码case channel3 <- value:// 执行的代码// 你可以定义任意数量的 casedefault:// 所有通道都没有准备好,执行的代码
}
  • 每个 case 都必须是一个通道
  • 所有 channel 表达式都会被求值
  • 所有被发送的表达式都会被求值
  • 如果任意某个通道可以进行,它就执行,其他被忽略。
  • 如果有多个 case 都可以运行,select 会随机公平地选出一个执行,其他不会执行。
    否则:
    • 如果有 default 子句,则执行该语句。
    • 如果没有 default 子句,select 将阻塞,直到某个通道 可以运行;Go 不会重新对 channel 或值进行求值。

实例1:

package Selectimport ("fmt""time"
)func Select() {c1 := make(chan string)c2 := make(chan string)go func() {time.Sleep(1 * time.Second)c1 <- "one"}()go func() {time.Sleep(2 * time.Second)c2 <- "two"}()for i := 0; i < 2; i++ {select {case msg1 := <-c1:fmt.Println("received", msg1)case msg2 := <-c2:fmt.Println("received", msg2)}}
}

在这里插入图片描述

  • 以上实例中,我们创建了两个通道 c1 和 c2。
    select 语句等待两个通道的数据。如果接收到 c1 的数据,就会打印 “received one”;如果接收到 c2 的数据,就会打印 “received two”。

实例2:

package Selectimport ("fmt""time"
)func Select1() {c1 := make(chan string)c2 := make(chan string)go func() {time.Sleep(1 * time.Second)c1 <- "one"}()go func() {time.Sleep(2 * time.Second)c2 <- "two"}()for i := 0; i < 2; i++ {select {case msg1 := <-c1:fmt.Println("received", msg1)case msg2 := <-c2:fmt.Println("received", msg2)}}
}func Select2() {// 定义两个通道ch1 := make(chan string)ch2 := make(chan string)// 启动两个 goroutine,分别从两个通道中获取数据go func() {for {ch1 <- "from 1"}}()go func() {for {ch2 <- "from 2"}}()// 使用 select 语句非阻塞地从两个通道中获取数据for {select {case msg1 := <-ch1:fmt.Println(msg1)case msg2 := <-ch2:fmt.Println(msg2)default:// 如果两个通道都没有可用的数据,则执行这里的语句fmt.Println("no message received")}}
}

在这里插入图片描述

  • 以上实例中,我们定义了两个通道,并启动了两个协程(Goroutine)从这两个通道中获取数据。在 main 函数中,我们使用 select 语句在这两个通道中进行非阻塞的选择,如果两个通道都没有可用的数据,就执行 default 子句中的语句。
    以上实例执行后会不断地从两个通道中获取到的数据,当两个通道都没有可用的数据时,会输出 “no message received”。

二、循环语句

1.for循环

for 循环是一个循环控制结构,可以执行指定次数的循环。
Go 语言的 For 循环有 3 种形式,只有其中的一种使用分号。

  • 和 C 语言的 for 一样:
for init; condition; post { }

init: 一般为赋值表达式,给控制变量赋初值;
condition: 关系表达式或逻辑表达式,循环控制条件;
post: 一般为赋值表达式,给控制变量增量或减量。

  • 和 C 的 while 一样:
for condition { }
  • 和 C 的 for(;;) 一样:
for { }
  • for 循环的 range 格式可以对 slice、map、数组、字符串等进行迭代循环。格式如下:
for key, value := range oldMap {newMap[key] = value
}

以上代码中的 key 和 value 是可以省略。
如果只想读取 key,格式如下:

for key := range oldMap

或者这样:

for key, _ := range oldMap

如果只想读取 value,格式如下:

for _, value := range oldMap

实例1:

package Forimport "fmt"func For() {sum := 0for i := 1; i <= 10; i++ {sum += i}fmt.Println(sum)
}

在这里插入图片描述

实例2:

package Forimport "fmt"func While() {sum := 1for sum <= 10 {sum += sum}fmt.Println(sum)
}

在这里插入图片描述

  • 以上实例是将init 和 post参数去掉,相当于是一个while循环

实例3:

package Forimport "fmt"func main() {sum := 0for {sum++ // 无限循环下去}fmt.Println(sum) // 无法输出
}
  • for后面什么也不跟就是无限循环;

实例4:

package Forimport "fmt"func Range() {strings := []string{"google", "runoob"}for i, s := range strings {fmt.Println(i, s)}numbers := [6]int{1, 2, 3, 5}for i, x := range numbers {fmt.Printf("第 %d 位 x 的值 = %d\n", i, x)}
}

在这里插入图片描述

  • For-each range 循环可以对字符串、数组、切片等进行迭代输出元素。

实例5:

package Forimport "fmt"func Range() {map1 := make(map[int]float32)map1[1] = 1.0map1[2] = 2.0map1[3] = 3.0map1[4] = 4.0// 读取 key 和 valuefor key, value := range map1 {fmt.Printf("key is: %d - value is: %f\n", key, value)}// 读取 keyfor key := range map1 {fmt.Printf("key is: %d\n", key)}// 读取 valuefor _, value := range map1 {fmt.Printf("value is: %f\n", value)}
}

在这里插入图片描述

  • For-each range也可以读取map中的k和v

三、defer语句

1.defer语句的作用

defer语句被用于预定对一个函数的调用。可以把这类被defer语句调用的函数称为延迟函数。
defer语句会将其后的函数调用推迟到当前所在函数体的生命周期结束后再执行,类似于c++的析构函数。这个特性常用于处理成对的操作,如打开/关闭文件、获取/释放锁、连接/断开连接等确保资源被适当地释放,即使在发生错误或提前返回的情况下也能保证执行。
defer作用:

  • 释放占用的资源
  • 捕捉处理异常
  • 输出日志

如果一个函数中有多个defer语句,它们会以LIFO(后进先出)的顺序执行。
在这里插入图片描述
实例

package Deferimport "fmt"func Defer() {defer fmt.Println("main end1")defer fmt.Println("main end2")fmt.Println("0")fmt.Println("1")
}

在这里插入图片描述

  • defer语句调用的函数会在当前函数体生命周期结束后再出栈执行,多个defer语句调用函数的顺序类似于堆栈,后进先出;

2.defer和return的先后顺序

package Deferimport "fmt"func deferFunc() int {fmt.Println("defer func called...")return 0
}func returnFunc() int {fmt.Println("return func caller...")return 0
}func ReturnAndDefer() int {defer deferFunc()return returnFunc()
}

在这里插入图片描述

  • 由于defer语句会将其后的函数调用推迟到当前所在函数体的生命周期结束后再出栈,而return语句是在}之前的,因此return会先执行,defer再执行;

3.recover错误拦截

运行时panic异常一旦被引发就会导致程序崩溃。

  • Go语言提供了专用于“拦截”运行时panic的内建函数recover它可以是当前的程序从运行时panic的状态中恢复并重新获得流程控制权
  • 注意:recover只有在defer调用的函数中有效。

实例1:

package mainimport "fmt"func recoverFunc(i int) {//定义10个元素的数组var arr [10]int//错误拦截要在产生错误前设置//这里使用匿名函数进行错误拦截,在进行defer调用//相当于这个匿名函数在recoverFunc的生命周期结束后才被调用defer func() {//设置recover拦截错误信息err := recover()//产生panic异常,打印错误信息if err != nil {fmt.Println(err)}}()//根据函数参数为数组元素赋值//如果i的值超过数组下标 会报错误:数组下标越界arr[i] = 2
}func main() {recoverFunc(10)fmt.Println("程序继续执行...")
}

在这里插入图片描述

  • 在上述实例中,我们定义了一个匿名函数来拦截panic,并用defer去掉用,这个匿名函数会在当前recoverFunc的生命周期结束后进行调用,recoverFunc函数中出现了数组越界的错误,之后被recover()拦截了,程序得以继续执行;

实例2:

package mainimport "fmt"func handlePanic() {if r := recover(); r != nil {fmt.Println("Recovered:", r)}
}func performTask() {defer handlePanic()fmt.Println("Performing some task...")panic("Oops! Something went wrong!")fmt.Println("Task completed.")
}func main() {performTask()fmt.Println("Main function continues.")
}

在这里插入图片描述

  • 在以上的实例中,panic函数调用后,异常被引发,当前performTask函数执行结束,defer调用的函数开始出栈,执行handlePanic函数,panic异常引发后,在handlePanic函数中recover拦截了异常,打印出错误信息,并让main函数继续运行。

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

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

相关文章

openEuler22.0.3安装oracle11.2.0.4报错总结

openEuler是CentOS8系列魔改来的 1.xstart无法打开报错x11拒绝转义 yum install *x11* vi /etc/ssh/sshd_config X11Forwarding yes systemctl restart sshd 2.执行runinstaller报错,无论是直接无法打开界面报错: when installed in the jdk 1.2 Linux 还是打开界面报错: no o…

网络服务DHCP与DNS

一 DHCP的工作原理&#xff08;租约过程&#xff09; 分类 1&#xff09;自动分配&#xff1a;分配到一个IP地址后永久使用 &#xff08;2&#xff09;手动分配&#xff1a;由DHCP服务器管理员指定IP&#xff08;打印机、报销系统&#xff09;把mac地址和ip地址做一个一一对…

Android基于Matrix绘制PaintDrawable设置BitmapShader,以手指触点为中心显示原图像圆图,Kotlin

Android基于Matrix绘制PaintDrawable设置BitmapShader&#xff0c;以手指触点为中心显示原图像圆图&#xff0c;Kotlin 手指在上面的图上移动&#xff0c;“剪切”出上面图中以手指触点为中心的图&#xff08;半径图&#xff09;&#xff0c;然后在下面的ImageView显示。 impor…

C++实现简单贪吃蛇游戏

文章目录 1 开发历程2 开发思路3 使用介绍4 源文件代码5 游戏截图6 小结 1 开发历程 游戏使用C语言开发&#xff0c;是博主某个下午心血来潮的结果&#xff0c;后面又花了点时间加了计分&#xff0c;记录历史得分的功能。 2 开发思路 其实贪吃蛇主要难在蛇身的移动上&#x…

(C#源码)LIMS实验室信息系统,管理实验室的样本、数据、实验和设备等信息

LIMS系统&#xff0c;LIMS实验室信息系统源码&#xff0c;C# LIMS系统源码&#xff0c; 什么是LIMS&#xff1f; LIMS即实验室信息管理系统&#xff08;Laboratory Information Management System&#xff09;&#xff0c;是一种专门为实验室设计的信息管理系统&#xff0c;用…

小程序基础学习(组件化)

&#xff08;一&#xff09;创建 找到components文件夹下面创建新的文件夹 然后再文件夹内创建component格式的文件 创建后这样 我创建的是my-info的文件夹以及my-info的components文件&#xff0c;跟着普通的页面一样 &#xff08;二&#xff09; 注册组件 找到你需要使用组…

leetcode:滑动窗口

目录 1.定长滑动窗口 1.1 几乎唯一子数组的最大和(使用map来计数) 1.2 长度为k子数组中的最大和 2.不定长滑动窗口 2.1 最多k个重复元素的最长子数组 2.2 绝对差不超过限制的最长连续子数组(multiset&#xff09; 2.3 将x减到0的最小操作数(正难则反 逆向思维) 2.4 统计…

Developer Tools for Game Creator 1

插件包含: 持久世界时间管理系统 单击以生成对象或预设 游戏内调试控制台 游戏内事件控制台 控制台管理控制 命令模板脚本 游戏内屏幕截图 低分辨率和高分辨率图像 缩略图生成 移动支持 使用Game Creator Action或拖放来激活和控制组件,无需编码。 通过此资产,您可以获得: …

Android 15即将到来,或将推出5大新功能特性

Android15 OneUI电池优化 三星最近完成了对其所有设备的稳定版 One UI 6.0 更新的推出&#xff0c;引起了用户的极大兴奋。据新出现的互联网统计数据显示&#xff0c;即将发布的基于 Android 15 的 One UI 7 将通过优化电池和功耗来重新定义用户体验&#xff0c;这是一项具有突…

React之自定义路由组件

开篇 react router功能很强大&#xff0c;可以根据路径配置对应容器组件。做到组件的局部刷新&#xff0c;接下来我会基于react实现一个简单的路由组件。 代码 自定义路由组件 import {useEffect, useState} from "react"; import React from react // 路由配置 e…

【C++】C++11中的常见语法(上)

C11 一、C11简介二、统一的列表初始化1.&#xff5b;&#xff5d;初始化2. std::initializer_list 三、声明1. auto2. decltype3. nullptr 四、右值引用和移动语义1. 左值引用和右值引用2. 左值引用与右值引用比较3. 右值引用使用场景和意义4. 右值引用引用左值及其一些更深入的…

Python知识点(史上最全)

Python期末考试知识点&#xff08;史上最全&#xff09; python简介 Python是一种解释型语言 Python使用缩进对齐组织代码执行&#xff0c;所以没有缩进的代码&#xff0c;都会在载入时自动执行 数据类型&#xff1a;整形 int 无限大 浮点型 float…

概率论与数理统计-第6章 参数估计

6.1 点估计问题概述 一、点估计的概念 二、评价估计量的标准 无偏性 定义1&#xff1a;设^ θ(X1,…,Xn)是未知参数θ的估计量&#xff0c;若E(^ θ)θ,则称^θ为θ的无偏估计量定理1&#xff1a;设X1,…,Xn,为取自总体X的样本&#xff0c;总体X的均值为μ&#xff0c;方差为…

快速打通 Vue 3(四):标签的 ref 属性与 Vue3 生命周期

很激动进入了 Vue 3 的学习&#xff0c;作为一个已经上线了三年多的框架&#xff0c;很多项目都开始使用 Vue 3 来编写了 这一组文章主要聚焦于 Vue 3 的新技术和新特性 如果想要学习基础的 Vue 语法可以看我专栏中的其他博客 Vue&#xff08;一&#xff09;&#xff1a;Vue 入…

centos 8.0 安装sysbench 1.0.17

序号步骤说明执行命令执行结果备注1 下载并解压sysbench-1.0.17.zip sysbench-1.0.17.zip2安装依赖文件 yum install automake libtool -y yum install /usr/include/libpq-fe.h 3安装sysbench cd sysbench-1.0.17 ./autogen.sh ./configure \ --prefix/sysbench \ --with-pgsq…

【Docker】Linux中Docker技术入门与实战及实用的常规命令

目录 一、引言 1. 说明&#xff1a; 2. Linux介绍 3. Docker简介 二、Docker三要素 1. 镜像&#xff08;Image&#xff09; 2. 容器&#xff08;Container&#xff09; 3. 仓库&#xff08;Repository&#xff09; 三、实现案例 1. 创建 2. 设置镜像 3. 开启设置 …

MidTool的AIGC与NFT的结合-艺术创作和版权保护的革新

在数字艺术和区块链技术的交汇点上&#xff0c;NFT&#xff08;非同质化代币&#xff09;正以其独特的方式重塑艺术品的收藏与交易。将MidTool&#xff08;https://www.aimidtool.com/&#xff09;的AIGC&#xff08;人工智能生成内容&#xff09;创作的图片转为NFT&#xff0c…

Windows启动MongoDB服务报错(错误 1053:服务没有及时响应启动或控制请求)

问题描述&#xff1a;修改MongoDB服务bin目录下的mongod.cfg&#xff0c;然后在任务管理器找到MongoDB服务-->右键-->点击【开始】&#xff0c;启动失败无提示&#xff1a; 右键点击任务管理器的MongoDB服务-->点击【打开服务】&#xff0c;跳转到服务页面-->找到M…

云服务器租用价格表,阿里云腾讯云华为云2024年优惠对比

作为多年站长使市面上大多数的云厂商的云服务器都使用过&#xff0c;很多特价云服务器都是新用户专享的&#xff0c;本文有老用户特价云服务器&#xff0c;阿腾云atengyun.com有多个网站、小程序等&#xff0c;国内头部云厂商阿里云、腾讯云、华为云、UCloud、京东云都有用过&a…

2024--Django平台开发-基础信息(一)

一、前置知识点 - Python环境搭建 (Python解释器、Pycharm、环境变量等) - 基础语法(条件、循环、输入输出、编码等) - 数据类型(整型、布尔型、字符串、列表、字典、元组、集合等) - 函数(文件操作、返回值、参数、作用域等) - 面向对象 (类、对象、封装、继承、多态等)包和模…