Golang教程二(判断,循环语句,函数,指针,init,defer)

目录

一、判断语句

1.if语句

2.switch语句

 二、循环语句

1.传统for循环

2.死循环

3.while模式

4.do-while模式

5.遍历切片

6.遍历map

7.break,continue

三、函数,指针 

1.函数定义 

2.匿名函数

3.高阶函数

4.闭包 

5.值传递和引用传递

 6.指针

 四、init函数和defer函数

1.init函数

2.defer函数 

 3.defer面试题


一、判断语句

1.if语句

package mainimport "fmt"func main() {fmt.Println("请输入你的年龄:")var age intfmt.Scan(&age)if age <= 18 {if age <= 10 {fmt.Println("儿童")} else {fmt.Println("未成年")}} else if age <= 35 {fmt.Println("青年")} else {fmt.Println("中老年")}
}

2.switch语句

可以理解为case的值就是switch的枚举结果

一般来说,go的switch的多选一,满足其中一个结果之后,就结束switch了

package mainimport "fmt"func main() {fmt.Println("请输入你的年龄:")var age intfmt.Scan(&age)switch {case age <= 0:fmt.Println("未出生")case age <= 18:fmt.Println("未成年")case age <= 35:fmt.Println("青年")default:fmt.Println("中年")}
}

 我输入一个12,我希望它能输出满足的所有条件,例如我希望它输出,未成年,青年

package mainimport "fmt"func main() {fmt.Println("请输入你的年龄:")var age intfmt.Scan(&age)switch {case age <= 0:fmt.Println("未出生")fallthroughcase age <= 18:fmt.Println("未成年")fallthroughcase age <= 35:fmt.Println("青年")default:fmt.Println("中年")}
}

 二、循环语句

1.传统for循环

package mainimport "fmt"func main() {var sum = 0for i := 0; i <= 100; i++ {sum += i}fmt.Println(sum)
}

2.死循环

package mainimport ("fmt""time"
)func main() {//每隔1秒打印当前的时间for {time.Sleep(1 * time.Second)fmt.Println(time.Now().Format("2006-01-02 15:04:05")) // 年月日时分秒的固定格式}
}

3.while模式

package mainimport "fmt"func main() {//由于golang没有while循环,如果需要,则是由for循环稍微变化得来i := 0sum := 0for i <= 100 {sum += ii++}fmt.Println(sum)
}

4.do-while模式

package mainimport "fmt"func main() {//do-while模式就是先执行一次循环体,再判断i := 0sum := 0for {sum += ii++if i == 101 {break}}fmt.Println(sum)
}

5.遍历切片

package mainimport "fmt"func main() {// 第一个参数是索引,第二个参数是值s := []string{"os", "lee"}for index, s2 := range s {fmt.Println(index, s2)}
}

6.遍历map

package mainimport "fmt"func main() {//第一个参数就是key,第二个就是values := map[string]int{"age":   24,"price": 1000,}for key, val := range s {fmt.Println(key, val)}
}

7.break,continue

  1. break用于跳出当前循环
  2. continue用于跳过本轮循环

三、函数,指针 

函数是一段封装了特定功能的可重用代码块,用于执行特定的任务或计算

函数接受输入(参数)并产生输出(返回值)

1.函数定义 

package mainimport "fmt"func add(n1 int, n2 int) int {fmt.Println(n1, n2)return n1 + n2
}// 参数类型一样,可以合并在一起
func add1(n1, n2 int) int {fmt.Println(n1, n2)return n1 + n2
}// 多个参数
func add2(numList ...int) {fmt.Println(numList)
}func main() {i := add(1, 2)fmt.Println(i)i2 := add1(1, 2)fmt.Println(i2)add2(1, 2, 3, 4)
}

2.匿名函数

匿名函数(Anonymous Function)是一种没有命名的函数定义。 

特点

  1. 无名称:匿名函数没有显式的名字,因此不能像普通函数那样通过名字被调用或在其他地方被引用。
  2. 内联定义:可以在需要使用函数的地方直接定义,无需单独的函数声明或定义部分。
  3. 简洁性:特别适合用于一次性使用的简单功能,避免了为一个小功能特意命名一个函数的繁琐。
  4. 可赋值给变量:匿名函数可以赋值给一个变量,通过变量名来调用,此时变量充当了函数的“代理名”。
  5. 可作为参数或返回值:匿名函数可以作为其他函数的参数或返回值,这是高阶函数的基础。
  6. 访问外部变量:匿名函数可以访问其定义时所在作用域内的变量,形成闭包。
package mainimport "fmt"func main() {var add = func(a, b int) int {return a + b}fmt.Println(add(1, 2))
}

3.高阶函数

高阶函数是指可以接收一个或多个函数作为参数,或者返回一个函数作为结果的函数。这样的函数提升了代码的抽象层次,使得我们能够以更通用和灵活的方式处理函数,从而简化代码并促进复用。

package mainimport "fmt"func ApplyToIntList(list []int, f func(int) int) []int {result := make([]int, len(list))for i, v := range list {result[i] = f(v)}return result
}func main() {// 编写一个高阶函数,接受一个整数列表和一个处理函数作为参数,返回处理函数对该列表所有元素应用后的结果列表。 示例代码:squareAll := ApplyToIntList([]int{1, 2, 3, 4}, func(x int) int { return x * x })fmt.Println(squareAll) // 输出:[1, 4, 9, 16]
}

4.闭包 

闭包是一种特殊的函数,是该函数和其周围环境(即自由变量)组成的绑定关系。当一个函数访问其外部作用域中的变量时,即使在其外部作用域已经结束(函数返回)后,只要闭包还在使用,这些变量仍会保持活跃。闭包常与高阶函数一起使用,作为高阶函数的返回值或参数。

package mainimport "fmt"func counter() func() int {count := 0return func() int {count++return count}
}func main() {// counter高阶函数,func() int是闭包counterFunc := counter()fmt.Println(counterFunc()) // 输出:1fmt.Println(counterFunc()) // 输出:2fmt.Println(counterFunc()) // 输出:3// 创建另一个计数器实例anotherCounter := counter()fmt.Println(anotherCounter()) // 输出:1
}

5.值传递和引用传递

  • 值传递:函数接收到的是实参的副本,对形参的修改不影响实参。
  • 引用传递:函数接收到的是实参的引用,对形参的修改直接影响实参。

稍微了解过编程的都应该知道,计算机上显示的所有的数据都是在内存里面的
也就是说,我们定义的一个变量,它也在内存里面有一块地

正常情况下来说,函数的参数是将之前那块地复制了一份出来

如何证明呢

package mainimport "fmt"func add(num int) {fmt.Println(&num) // 可以看到,这个n的内存地址和外面num的内存地址是明显不一样的num = 2           // 这里的修改不会影响外面的num
}func main() {num := 20fmt.Println(&num)add(num)fmt.Println(num) // 20
}

也就是说,在函数里面不管怎么修改这个参数,都不会影响原来的那个值

但是,如果我需要在函数体内修改变量的值呢?

这就需要用到引用传递了

我们直接将变量的内存地址传递进去

package mainimport "fmt"func add(num *int) {fmt.Println(num) // 内存值是一样的*num = 2         // 这里的修改会影响外面的num
}func main() {num := 20fmt.Println(&num)add(&num)fmt.Println(num) // 成功修改 2
}

 6.指针

指针是一种特殊的数据类型,它存储的是另一个变量的内存地址。简单来说,指针就是一个变量的“地址标签”,通过这个标签,程序可以直接访问和操作该变量在内存中的值。理解指针的关键在于以下几个方面:

  1. 内存地址与值

    • 变量在内存中占据一块特定的空间,每个变量都有一个唯一的内存地址。
    • 变量的值就是存储在这块内存空间中的数据。
  2. 指针变量声明

    • 声明一个指针变量时,使用星号 * 作为前缀来表示这是一个指针类型,并指定它指向的值的类型。
    • 声明格式为 var pointerName *typeName,其中 pointerName 是指针变量名,typeName 是它所指向的值的类型。
    • 例如,var xPtr *int 声明了一个名为 xPtr 的指针,它指向一个整型(int)变量。
  3. 指针初始化与赋值

    • 初始化指针时,通常使用取地址运算符 & 来获取一个变量的内存地址,并将其赋值给指针变量。
    • 例如,x := 10; xPtr := &x,这里 xPtr 被初始化为变量 x 的内存地址。
  4. 解引用与指针操作

    • 使用指针访问或修改其指向的值时,需要通过解引用操作。解引用是使用指针变量前的星号 * 运算符来实现的。
    • 例如,*xPtr = 20 会通过 xPtr 修改其指向的整型变量的值为 20。
    • 同样,y := *xPtr 会通过 xPtr 获取其指向的值,并将其赋值给变量 y
  5. 指针运算限制

    • Go语言中的指针不能进行算术运算(如加减法),这是与C语言的重要区别。试图对指针进行算术运算会在编译阶段报错。
  6. 指针用途

    • 提高性能:通过指针传递大对象时,避免了值拷贝,提高了效率。
    • 修改函数外部变量:函数参数为指针时,函数内部可以修改外部变量的值。
    • 实现动态数据结构:如链表、树等,节点间通过指针连接。
    • 回调函数和闭包:闭包常常需要捕获并保持对外部变量的引用,这通常是通过指针实现的。

我们只需要记住

&是取地址,*是解引用,获取这个地址指向的值

 四、init函数和defer函数

1.init函数

init函数用于在程序启动时执行一些初始化任务,如设置默认值、打开数据库连接、加载配置等。

init函数具有以下特点:

  1. 无须显式调用:init函数由Go运行时自动调用,无需在代码中显式调用。
  2. 无参数、无返回值:init函数没有参数,也不返回任何值。
  3. 可出现在任何包、任何源文件中:一个包(package)中可以有多个init函数,分布在不同的源文件中。

执行顺序:init函数的执行顺序遵循以下规则:

  1. 包内顺序:同一个包中,init函数按照它们在源文件中出现的顺序依次执行。如果一个源文件中有多个init函数,那么它们按照从上到下的顺序执行。
  2. 包间顺序:不同包之间的init函数按照包导入的依赖关系进行排序。首先执行被导入包(间接或直接)的所有init函数,然后才执行导入包本身的init函数。具体而言,如果包A导入了包B,那么包B中的所有init函数将在包A中的所有init函数之前执行。
  3. 主包(main包):主包(包含main()函数的包)的init函数总是在所有非主包的init函数之后执行。

2.defer函数 

defer语句用于延迟执行一个函数调用,直到包含该defer语句的函数返回时才执行。defer语句通常用于资源清理、解锁、关闭文件、网络连接等需要确保在函数结束时执行的操作。

defer函数具有以下特点:

  1. 延迟执行defer语句指定的函数调用会在包含它的函数(或方法)即将返回时,无论正常返回还是通过panic异常返回,都会被执行。这种特性使得defer函数特别适合用于确保资源的正确释放,即使在函数执行过程中发生错误或异常。

  2. 后进先出(LIFO)顺序:在同一函数中,如果有多个defer语句,它们的执行顺序与声明顺序相反,即最后声明的defer函数最先执行,最先声明的defer函数最后执行。这种顺序类似于栈的行为。

  3. 参数求值defer语句中的函数参数在defer语句执行时(即函数调用前)就已经求值,但函数体的执行是在函数返回时。

注意事项:

  1. defer函数的返回值会被计算,但会被丢弃,因此defer通常用于无返回值的函数调用。
  2. 大量使用defer可能会对函数的性能造成轻微影响,尤其是在函数调用非常频繁的场景。应合理使用,避免过度依赖。
  3. 如果defer函数内部引发了panic,后续的defer函数仍会按照后进先出的顺序执行,直到遇到recover函数捕获该panic,或者函数结束时panic传播到上层调用者。

 3.defer面试题

package mainfunc DeferFunc1(i int) (t int) {// t = 1t = idefer func() {t += 3}()return t
}
func DeferFunc2(i int) int {t := idefer func() {t += 3}()return t
}
func DeferFunc3(i int) (t int) {defer func() {t += i}()return 2
}// DeferFunc1中,有名返回(指定返回值命名func test() (t int)),执行 return 语句时,并不会再创建临时变量保存,defer 语句修改了t,即对返回值产生了影响,所以返回4。
// DeferFunc2中,无名返回(返回值没有指定命名),执行Return语句后,Go会创建一个临时变量保存返回值,defer 语句修改的是 t,而不是临时变量,所以返回1。
// DeferFunc3中,有名返回,执行 return 语句时,把2赋值给t,defer 语句再执行t+1,所以返回3。
func main() {println(DeferFunc1(1))println(DeferFunc2(1))println(DeferFunc3(1))
}

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

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

相关文章

Erlang 常用数据结构实现

Erlang 是一种函数式编程语言&#xff0c;其常用数据结构主要包括元组&#xff08;tuple&#xff09;、列表&#xff08;list&#xff09;、字典&#xff08;dict&#xff09;和二进制&#xff08;binary&#xff09;等。下面是这些常用数据结构的实现示例&#xff1a; 元组&a…

Hadoop技术详解

Hadoop技术详解 Hadoop技术作为大数据处理的重要基石&#xff0c;已经在多个行业中得到了广泛的应用。本文将对Hadoop技术进行详细的讲解&#xff0c;帮助读者更好地理解和运用这项技术。 Hadoop是由Apache基金会开发的一个开源分布式系统基础架构&#xff0c;它允许用户在不…

模型自由度与残差自由度

模型的自由度&#xff08;degrees of freedom&#xff09;通常指的是在模型参数估计过程中剩余可以自由变化的数量。 当我们谈论残差平方和&#xff08;RSS&#xff09;或误差项的自由度时&#xff0c;确实使用的是n - k - 1的公式&#xff0c;这里&#xff1a; n 是样本大小…

微信小程序 uniapp+vue动漫交流系统 java(springboot+ssm)/python(flask+django)/

小程序Android端运行软件 微信开发者工具/hbuiderx uni-app框架&#xff1a;使用Vue.js开发跨平台应用的前端框架&#xff0c;编写一套代码&#xff0c;可编译到Android、小程序等平台。 前端&#xff1a;HTML5,CSS3 VUE 后端&#xff1a;java(springbootssm)/python(flaskdja…

python爬虫 - 爬取微博热搜数据

文章目录 python爬虫 - 爬取微博热搜数据1. 第一步&#xff1a;安装requests库和BeautifulSoup库2. 第二步&#xff1a;获取爬虫所需的header和cookie3. 第三步&#xff1a;获取网页4. 第四步&#xff1a;解析网页5. 第五步&#xff1a;分析得到的信息&#xff0c;简化地址6. 第…

大象机器人发布智能遥操作机械臂组合myArm MC,加速具身智能研究与发展!

在全球工业自动化和智能化加速发展的今天&#xff0c;机器人行业正经历着翻天覆地的变化。具身智能研究&#xff0c;作为人工智能领域的关键分支&#xff0c;正努力在精准动作控制、高层次自主决策能力以及自然人机交互体验上赋予机器人新的能力。 在此背景下&#xff0c;大象机…

Linux命令-dpkg-statoverride命令(Debian Linux中覆盖文件的所有权和模式)

说明 dpkg-statoverride命令 用于Debian Linux中覆盖文件的所有权和模式&#xff0c;让dpkg于包安装时使得文件所有权与模式失效 语法 dpkg-statoverride(选项)选项 -add&#xff1a;为文件添加一个改写&#xff1b; --remove&#xff1a;为文件删除一个改写&#xff1b; -…

Jackson 2.x 系列【14】特征配置篇之 MapperFeature

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Jackson 版本 2.17.0 源码地址&#xff1a;https://gitee.com/pearl-organization/study-jaskson-demo 文章目录 1. 前言2. 通用2.1 USE_ANNOTATIONS2.2 USE_GETTERS_AS_SETTERS2.3 PROPAGATE_TR…

吴恩达机器学习理论基础解读—线性模型(单一特征拟合)

吴恩达机器学习理论基础——线性模型 机器学习最常见的形式监督学习&#xff0c;无监督学习 线性回归模型概述 应用场景一&#xff1a;根据房屋大小预测房价 应用场景二&#xff1a;分类算法&#xff08;猫狗分类&#xff09; 核心概念&#xff1a;将训练模型的数据称为数…

宝塔面板部署腾讯云的域名

一、腾讯云&#xff0c;搜索我的证书&#xff0c;点击打开如图所示&#xff0c;点击下砸 二、点击宝塔的证书&#xff0c;然后下载到桌面 三、解压 四、打开宝塔&#xff0c;网站》自己的项目列表中要绑定的ssl 五、对应的文件内容复制进去&#xff0c;保存并启用证书 六、有了…

springboot相关报错解决

Caused by: java.lang.ClassNotFoundException: 目录 Caused by: java.lang.ClassNotFoundException: org.springframework.context.event.GenericApplicationListener spring-boot-dependencies:jar:2.1.9.RELEASE was not found org.springframework.context.event.Generi…

C++/QT 医院信息管理系统

一、项目介绍 &#xff08;1&#xff09;管理员、居民、医生三个角色登录&#xff1b;居民可注册账号登录&#xff0c;医生由管理员添加&#xff0c;管理员权限最高 &#xff08;2&#xff09;管理员&#xff1a; 模块一&#xff1a;信息管理&#xff08;医生信息管理、医院…

C语言入门算法——回文数

题目描述&#xff1a; 若一个数&#xff08;首位不为零&#xff09;从左向右读与从右向左读都一样&#xff0c;我们就将其称之为回文数。 例如&#xff1a;给定一个十进制数 56&#xff0c;将 56 加 65&#xff08;即把 56 从右向左读&#xff09;&#xff0c;得到 121 是一个…

MySQL出现You can‘t specify target table for update in FROM clause错误的解决方法

分析原因 在MySQL中&#xff0c;可能会遇到You cant specify target table 表名 for update in FROM clause这样的错误 它的意思是说&#xff0c;不能在同一语句中&#xff0c;先select出同一表中的某些值&#xff0c;再update这个表&#xff0c;即不能依据某字段值做判断再来…

自回归模型

自回归模型是一类序列生成模型&#xff0c;其生成的输出依赖于先前的输出。换句话说&#xff0c;模型在生成序列的过程中&#xff0c;每个时间步生成的值都依赖于前面时间步生成的值。这种模型通常用于处理序列数据&#xff0c;如文本、音频、时间序列等。 在自然语言处理中&a…

Python计算多个表格中多列数据的平均值与标准差并导出为新的Excel文件

本文介绍基于Python语言&#xff0c;对一个或多个表格文件中多列数据分别计算平均值与标准差&#xff0c;随后将多列数据对应的这2个数据结果导出为新的表格文件的方法。 首先&#xff0c;来看一下本文的需求。现有2个.csv格式的表格文件&#xff0c;其每1列表示1个变量&#x…

CCD相机均匀光源积分球

均匀光源积分球在摄影和成像领域具有重要的作用&#xff0c;它可以为CCD相机提供高质量、均匀光源的关键设备。CCD相机&#xff0c;即电荷耦合器件相机&#xff0c;以其高灵敏度、高分辨率和快速响应等特点广泛应用于科研、工业检测、医疗影像等多个领域。然而&#xff0c;为了…

Git Clone succeeded, but checkout failed

Clone succeeded, but checkout failed&#xff1a; Filename too long 原因&#xff1a; 由于系统限制&#xff0c;路径太长&#xff0c;无法检出 解决方案&#xff1a; # git允许长路径&#xff0c;在已clone的仓库执行 git config core.longpaths true # 再次检出 git ch…

Sarson Funds 在 Casper 测试网推出稳定币 csprUSD

Sarson Funds 与 Casper Association 合作&#xff0c;在 Casper Network &#xff08;CSPR&#xff09;测试网上推出了 csprUSD 稳定币。 作为最新的法币背书型稳定币&#xff0c;csprUSD 进入了数字货币市场&#xff0c;与 Ripple 和 Cardano 等组织近期推出的产品定位一致。…

libcurl 简单实用

LibCurl是一个开源的免费的多协议数据传输开源库&#xff0c;该框架具备跨平台性&#xff0c;开源免费&#xff0c;并提供了包括HTTP、FTP、SMTP、POP3等协议的功能&#xff0c;使用libcurl可以方便地进行网络数据传输操作&#xff0c;如发送HTTP请求、下载文件、发送电子邮件等…