【golang学习总结】7 golang函数、包和错误处理

本文介绍SpringBoot相关内容。和【跨考菌】一起加油吧~

在这里插入图片描述

如果你有收获,记得帮博主一键三连哦


1 函数

1.1 函数语法

【golang学习总结】7 golang函数、包和错误处理_第1张图片

1.2 简单案例

【golang学习总结】7 golang函数、包和错误处理_第2张图片
【golang学习总结】7 golang函数、包和错误处理_第3张图片

1.3 return语句

【golang学习总结】7 golang函数、包和错误处理_第4张图片
在这里插入图片描述
案例1
【golang学习总结】7 golang函数、包和错误处理_第5张图片
案例2
忽略某个返回值,用_占位符来替代。
【golang学习总结】7 golang函数、包和错误处理_第6张图片

1.4 使用细节

  1. 函数的形参列表可以是多个, 返回值列表也可以是多个。
  2. 形参列表和返回值列表的数据类型可以是值类型和引用类型。
  3. 函数的命名遵循标识符命名规范, 首字母不能是数字, 首字母大写该函数可以被本包文件和其
    它包文件使用, 类似 public , 首字母小写, 只能被本包文件使用, 其它包文件不能使用, 类似 private
  4. 函数中的变量是局部的, 函数外不生效【案例说明】
    【golang学习总结】7 golang函数、包和错误处理_第7张图片
  5. 基本数据类型和数组默认都是值传递的, 即进行值拷贝。 在函数内修改, 不会影响到原来的值。
    【golang学习总结】7 golang函数、包和错误处理_第8张图片
  6. 如果希望函数内的变量能修改函数外的变量(指的是默认以值传递的方式的数据类型), 可以传
    入变量的地址&, 函数内以指针的方式操作变量。 从效果上看类似引用 。
    【golang学习总结】7 golang函数、包和错误处理_第9张图片
  7. Go 函数不支持函数重载
    【golang学习总结】7 golang函数、包和错误处理_第10张图片
  8. 在 Go 中, 函数也是一种数据类型, 可以赋值给一个变量, 则该变量就是一个函数类型的变量
    了。 通过该变量可以对函数调用.
    【golang学习总结】7 golang函数、包和错误处理_第11张图片
  9. 函数既然是一种数据类型, 因此在 Go 中, 函数可以作为形参, 并且调用

【golang学习总结】7 golang函数、包和错误处理_第12张图片
10) 为了简化数据类型定义, Go 支持自定义数据类型
基本语法: type 自定义数据类型名 数据类型 // 理解: 相当于一个别名
案例: type myInt int // 这时 myInt 就等价 int 来使用了.
案例: type mySum func (int, int) int // 这时 mySum 就等价 一个 函数类型 func (int, int) int
【golang学习总结】7 golang函数、包和错误处理_第13张图片
11) 支持对函数返回值命名
【golang学习总结】7 golang函数、包和错误处理_第14张图片
12) 使用 _ 标识符, 忽略返回值
【golang学习总结】7 golang函数、包和错误处理_第15张图片
13) Go 支持可变参数
【golang学习总结】7 golang函数、包和错误处理_第16张图片
【golang学习总结】7 golang函数、包和错误处理_第17张图片

1.5 init函数

1.5.1 基本介绍

每一个源文件都可以包含一个 init 函数, 该函数会在 main 函数执行前, 被 Go 运行框架调用, 也就是说 init 会在 main 函数前被调用

1.5.2 案例说明

【golang学习总结】7 golang函数、包和错误处理_第18张图片
【golang学习总结】7 golang函数、包和错误处理_第19张图片

1.5.3 使用细节

  1. 如果一个文件同时包含全局变量定义, init 函数和 main 函数, 则执行的流程全局变量定义->init
    函数->main 函数

    【golang学习总结】7 golang函数、包和错误处理_第20张图片
  2. init 函数最主要的作用, 就是完成一些初始化的工作, 比如下面的案例
    【golang学习总结】7 golang函数、包和错误处理_第21张图片
  3. 细节说明: 面试题: 案例如果 main.go 和 utils.go 都含有 变量定义, init 函数时, 执行的流程
    又是怎么样的呢?
    【golang学习总结】7 golang函数、包和错误处理_第22张图片

1.6 匿名函数

1.6.1 介绍

Go 支持匿名函数, 匿名函数就是没有名字的函数, 如果我们某个函数只是希望使用一次, 可以考
虑使用匿名函数, 匿名函数也可以实现多次调用。

1.6.2 使用方式

使用方式1
在定义匿名函数时就直接调用, 这种方式匿名函数只能调用一次。
【golang学习总结】7 golang函数、包和错误处理_第23张图片

使用方式2
将匿名函数赋给一个变量(函数变量), 再通过该变量来调用匿名函数
【golang学习总结】7 golang函数、包和错误处理_第24张图片

1.6.3 全局匿名函数

如果将匿名函数赋给一个全局变量, 那么这个匿名函数, 就成为一个全局匿名函数, 可以在程序有效。
【golang学习总结】7 golang函数、包和错误处理_第25张图片

2 包

2.1 简单说明

go 的每一个文件都是属于一个包的, 也就是说 go 是以包的形式来管理文件和项目目录结构
的。

包的三大作用
区分相同名字的函数、 变量等标识符
当程序文件很多时,可以很好的管理项目
控制函数、 变量等访问范围, 即作用域

2.2 语法格式

  • 打包基本语法
    package 包名
  • 引入包的基本语法
    import “包的路径”

2.3 简单使用

我们将 func Cal 定义到文件 utils.go , 将 utils.go 放到一个包中, 当
其它文件需要使用到 utils.go 的方法时, 可以 import 该包, 就可以使用了。

【golang学习总结】7 golang函数、包和错误处理_第26张图片
utils.go:
【golang学习总结】7 golang函数、包和错误处理_第27张图片
main.go文件:
【golang学习总结】7 golang函数、包和错误处理_第28张图片

2.4 使用细节

  1. 在给一个文件打包时, 该包对应一个文件夹, 比如这里的 utils 文件夹对应的包名就是 utils,
    文件的包名通常和文件所在的文件夹名一致, 一般为小写字母。
  2. 当一个文件要使用其它包函数或变量时, 需要先引入对应的包
     引入方式 1: import “包名”
     引入方式 2:
import (
	"包名"
	"包名"
)

 package 指令在 文件第一行, 然后是 import 指令。
 在 import 包时, 路径从 $GOPATH 的 src 下开始, 不用带 src , 编译器会自动从 src 下开始引入
3) 为了让其它包的文件, 可以访问到本包的函数, 则该函数名的首字母需要大写, 类似其它语言
的 public ,这样才能跨包访问。 比如 utils.go 的
【golang学习总结】7 golang函数、包和错误处理_第29张图片
4) 在访问其它包函数, 变量时, 其语法是 包名.函数名, 比如这里的 main.go 文件中
在这里插入图片描述
5) 如果包名较长, Go 支持给包取别名, 注意细节: 取别名后, 原来的包名就不能使用了
【golang学习总结】7 golang函数、包和错误处理_第30张图片
说明: 如果给包取了别名, 则需要使用别名来访问该包的函数和变量。
6) 在同一包下, 不能有相同的函数名(也不能有相同的全局变量名) , 否则报重复定义
7) 如果你要编译成一个可执行程序文件, 就需要将这个包声明为 main , 即 package main .这个就是一个语法规范, 如果你是写一个库 , 包名可以自定义
【golang学习总结】7 golang函数、包和错误处理_第31张图片

3 闭包

3.1 基本介绍

闭包就是一个函数和与其相关的引用环境组合的一个整体(实体)

【golang学习总结】7 golang函数、包和错误处理_第32张图片

  1. AddUpper 是一个函数返回的数据类型是 fun (int) int
  2. 闭包的说明
    【golang学习总结】7 golang函数、包和错误处理_第33张图片
    返回的是一个匿名函数, 但是这个匿名函数引用到函数外的 n ,因此这个匿名函数就和 n 形成一
    个整体, 构成闭包。
  3. 大家可以这样理解: 闭包是类, 函数是操作, n 是字段。 函数和它使用到 n 构成闭包。
  4. 当我们反复的调用 f 函数时, 因为 n 是初始化一次, 因此每调用一次就进行累计。
  5. 我们要搞清楚闭包的关键, 就是要分析出返回的函数它使用(引用)到哪些变量, 因为函数和它引
    用到的变量共同构成闭包。
  6. 对上面代码的一个修改, 加深对闭包的理解
    【golang学习总结】7 golang函数、包和错误处理_第34张图片

3.2 闭包案例

请编写一个程序, 具体要求如下

  1. 编写一个函数 makeSuffix(suffix string) 可以接收一个文件后缀名(比如.jpg), 并返回一个闭包
  2. 调用闭包, 可以传入一个文件名, 如果该文件名没有指定的后缀(比如.jpg) ,则返回 文件名.jpg , 如果已经有.jpg 后缀, 则返回原文件名。
  3. 要求使用闭包的方式完成
  4. strings.HasSuffix , 该函数可以判断某个字符串是否有指定的后缀。
// 1)编写一个函数 makeSuffix(suffix string)  可以接收一个文件后缀名(比如.jpg),并返回一个闭包
// 2)调用闭包,可以传入一个文件名,如果该文件名没有指定的后缀(比如.jpg) ,则返回 文件名.jpg , 如果已经有.jpg后缀,则返回原文件名。
// 3)要求使用闭包的方式完成
// 4)strings.HasSuffix , 该函数可以判断某个字符串是否有指定的后缀。

func makeSuffix(suffix string) func (string) string {

	return func (name string) string {
		//如果 name 没有指定后缀,则加上,否则就返回原来的名字
		if !strings.HasSuffix(name, suffix)  {
			return name + suffix
		}

		return name
	}
}

【golang学习总结】7 golang函数、包和错误处理_第35张图片
代码总结和说明:

  1. 返回的匿名函数和 makeSuffix (suffix string) 的 suffix 变量 组合成一个闭包,因为 返回的函数引用到 suffix 这个变量
  2. 我们体会一下闭包的好处, 如果使用传统的方法, 也可以轻松实现这个功能, 但是传统方法需要每次都传入 后缀名, 比如 .jpg ,而闭包因为可以保留上次引用的某个值, 所以我们传入一次就可以反复使用。 大家可以仔细的体会一把!

4 defer

4.1 为什么需要defer

在函数中, 程序员经常需要创建资源(比如: 数据库连接、 文件句柄、 锁等) , 为了在函数执行完
毕后, 及时的释放资源, Go 的设计者提供 defer (延时机制)。

4.2 使用案例

【golang学习总结】7 golang函数、包和错误处理_第36张图片

4.3 使用细节和注意事项

  1. 当 go 执行到一个 defer 时, 不会立即执行 defer 后的语句, 而是将 defer 后的语句压入到一个栈
    中、, 然后继续执行函数下一个语句。
  2. 当函数执行完毕后, 在从 defer 栈中, 依次从栈顶取出语句执行(注: 遵守栈 先入后出的机制)
  3. 在 defer 将语句放入到栈时, 也会将相关的值拷贝同时入栈。 请看一段代码:

【golang学习总结】7 golang函数、包和错误处理_第37张图片

4.4 defer核心功能

当函数执行完毕后, 可以及时的释放函数创建的资源。
【golang学习总结】7 golang函数、包和错误处理_第38张图片
说明:

  1. 在 golang 编程中的通常做法是, 创建资源后, 比如(打开了文件, 获取了数据库的链接, 或者是
    锁资源), 可以执行 defer file.Close() defer connect.Close()
  2. 在 defer 后, 可以继续使用创建资源.
  3. 当函数完毕后, 系统会依次从 defer 栈中, 取出语句, 关闭资源.
  4. 这种机制, 非常简洁, 程序员不用再为在什么时机关闭资源而烦心。

5 函数的传递方式

值类型参数默认就是值传递, 而引用类型参数默认就是引用传递。

5.1 两种传递方式

  1. 值传递
  2. 引用传递

其实, 不管是值传递还是引用传递, 传递给函数的都是变量的副本, 不同的是, 值传递的是值的拷贝, 引用传递的是地址的拷贝, 一般来说, 地址拷贝效率高, 因为数据量小, 而值拷贝决定拷贝的数据大小, 数据越大, 效率越低。

5.2 值类型和引用类型

1) 值类型: 基本数据类型 int 系列, float 系列, bool, string 、 数组和结构体 struct
2) 引用类型: 指针、 slice 切片、 map、 管道 chan、 interface 等都是引用类型

5.3 值传递和引用传递的使用特点

【golang学习总结】7 golang函数、包和错误处理_第39张图片
3) 如果希望函数内的变量能修改函数外的变量, 可以传入变量的地址&, 函数内以指针的方式操作变量。 从效果上看类似引用 。 这个案例在前面详解函数使用注意事项的
【golang学习总结】7 golang函数、包和错误处理_第40张图片

6 变量的作用域

  1. 函数内部声明/定义的变量叫局部变量, 作用域仅限于函数内部
    【golang学习总结】7 golang函数、包和错误处理_第41张图片
  2. 函数外部声明/定义的变量叫全局变量, 作用域在整个包都有效, 如果其首字母为大写, 则作用
    域在整个程序有效
    【golang学习总结】7 golang函数、包和错误处理_第42张图片
  3. 如果变量是在一个代码块, 比如 for / if 中, 那么这个变量的的作用域就在该代码块

【golang学习总结】7 golang函数、包和错误处理_第43张图片

注意事项

【golang学习总结】7 golang函数、包和错误处理_第44张图片

你可能感兴趣的:(golang学习总结,golang,defer,函数)