Go学习笔记
目录
Go语言基础
函数
函数
是组织好的、可重复使用的、用于执行指定任务的代码块。- Go语言中支持
函数
、匿名函数
和闭包
, 并且函数在Go语言中属于 “一等公民” 。
函数定义
- Go语言中定义函数使用
func
关键字.
|
|
- 名词解析:
- 函数名: 由字母、数字、下划线组成。但函数名的第一个字母不能是数字。在同一个包内, 函数名也称不能重名。
- 参数: 参数由
参数变量
和参数变量类型
组成, 多个参数之间使用,
分隔。 - 返回值: 返回值由
返回值变
量和其变量类型
组成, 也可以只写返回值的类型, 多个返回值必须用()
包裹, 并用,
分隔。 - 函数体: 实现指定功能的代码块。
|
|
- 输出:
|
|
函数参数
- 函数参数由
参数变量
和参数变量类型
组成, 如果相邻变量的类型相同, 则可以省略类型。 - 函数参数类型相同时可以简写, 如:
func sum(x, y int)
- Go语言是没有 默认参数的
|
|
- 输出:
|
|
|
|
- 输出:
|
|
函数可变参数
可变参数
是指函数的参数数量不固定, Go语言中的可变参数通过在参数名后加...
来标识。可变参数
要放在参数最后面, 如:func a(x int, y...int)
|
|
- 输出:
|
|
函数返回值
- Go语言中通过
return
关键字向外输出返回值。 - Go语言中函数支持多返回值, 函数如果有多个返回值时必须用
()
将所有返回值包裹起来。 - 函数定义时可以给返回值命名, 并在函数体中直接使用这些变量, 最后通过
return
关键字返回。 - 多返回值也支持类型简写
|
|
- 输出:
|
|
defer语句
Go语言中的
defer
语句会将其后面跟随的语句进行延迟处理。在defer
归属的函数即将返回时, 将延迟处理的语句按defer
定义的逆序进行执行, 也就是说, 先被defer
的语句最后被执行, 最后被defer
的语句,最先被执行。由于
defer
语句延迟调用的特性,所以defer
语句能非常方便的处理资源释放问题。比如: 资源清理、文件关闭、解锁及记录时间等。在Go语言的函数中
return
语句在底层并不是原子操作, 它分为给返回值赋值和RET指令两步。而defer
语句执行的时机就在返回值赋值操作后, RET指令执行前。
|
|
|
|
- 输出:
|
|
defer 题目分析
|
|
- 输出:
|
|
函数 变量作用域
- 函数
全局变量
与局部变量
同时存在时, 优先使用 函数内定义的局部变量
, 然后在使用全局变量
。
|
|
- 输出:
|
|
函数类型与变量
- 函数类型变量
|
|
- 输出:
|
|
高阶函数
高阶函数分为
函数作为参数
和函数作为返回值
两部分。函数作为参数
|
|
- 输出:
|
|
- 函数作为返回值
|
|
- 输出
|
|
匿名函数和闭包
- 匿名函数 - 匿名函数就是没有函数名的函数。
- 匿名函数多用于实现回调函数和闭包。
|
|
|
|
- 输出:
|
|
闭包
- 闭包指的是一个函数和与其相关的引用环境组合而成的实体。简单来说:
闭包=函数+引用环境(外层变量的引用)
。
|
|
- 输出:
|
|
|
|
- 输出:
|
|
- 闭包的应用一
|
|
- 输出:
|
|
- 闭包的应用二
|
|
- 输出:
|
|
内置函数
内置函数 | 说明 |
---|---|
close | 主要用来关闭channel |
len | 用来求长度,比如string、array、slice、map、channel |
new | 用来分配内存,主要用来分配值类型,比如int、struct。返回的是指针 |
make | 用来分配内存,主要用来分配引用类型,比如chan、map、slice |
append | 用来追加元素到数组、slice中 |
panic和recover | 用来做错误处理 |
panic/recover
- Go语言中 版本小于等于
1.12
是没有异常机制, 但是使用panic/recover
模式来处理错误。panic
可以在任何地方引发。 recover()
必须搭配defer
使用。defer
一定要在可能引发panic
的语句之前定义。
- Go语言中 版本小于等于
引发 panic
|
|
- 输出:
|
|
- 使用 recover 恢复错误
|
|
- 输出:
|
|
函数练习题
|
|
|
|
- 输出:
|
|
指针
- Go语言中的指针区别于C/C++中的指针, 不能进行偏移和运算, 是安全指针。
- Go语言中的指针需要先知道3个概念: 指针地址、指针类型和指针取值。
- Go语言中的函数传参都是值拷贝, 当我们想要修改某个变量的时候, 我们可以创建一个指向该
变量地址
的指针变量
。传递数据使用指针, 而无须拷贝数据。类型指针
不能进行偏移和运算。Go语言中的指针操作非常简单, 只需要记住两个符号:&(取地址)
和*(根据地址取值)
。 - 取地址操作符
&
和取值操作符*
是一对互补操作符,&
取出地址,*
根据地址取出地址指向的值。 - 变量、指针地址、指针变量、取地址、取值的相互关系和特性如下:
- 对变量进行取地址
&
操作, 可以获得这个变量的指针变量。 - 指针变量的值是指针地址。
- 对指针变量进行取值
*
操作, 可以获得指针变量指向的原变量的值。
- 对变量进行取地址
指针地址和指针类型
每个变量在运行时都拥有一个地址, 这个地址代表变量在内存中的位置。Go语言中使用
&
字符放在变量前面对变量进行"取地址"操作。 Go语言中的值类型(int、float、bool、string、array、struct)都有对应的指针类型, 如:*int
、*int64
、*string
等。取变量指针的语法:
ptr := &v
- v: 代表被取地址的变量, 类型为T
- ptr: 用于接收地址的变量, ptr的类型就为*T, 称做T的指针类型。*代表指针。
|
|
- 输出:
|
|
指针取值
- 在对普通变量使用
&
操作符取地址后会获得这个变量的指针, 然后可以对指针使用*
操作,也就是指针取值。
|
|
- 输出:
|
|
指针传值
|
|
- 输出:
|
|
new和make
Go语言中
new
和make
是内建的两个函数, 主要用来分配内存。new
new
是一个内置的函数,它的函数签名:func new(Type) *Type
,Type
表示类型,new
函数只接受一个参数, 这个参数是一个类型.*Type
表示类型指针,new
函数返回一个指向该类型内存地址的指针。new
函数不太常用, 使用new
函数得到的是一个类型的指针,并且该指针对应的值为该类型的零值。
|
|
- 输出:
|
|
make
也是用于内存分配的,区别于new
, 它只用于slice
、map
以及chan
的内存创建, 而且它返回的类型就是这三个类型本身, 而不是他们的指针类型, 因为这三种类型就是引用类型, 所以就没有必要返回他们的指针了。make
函数的函数签名func make(t Type, size ...IntegerType) Type
make
函数是无可替代的, 我们在使用slice
、map
以及channel
的时候, 都需要使用make
进行初始化, 然后才可以对它们进行操作。
|
|
- 输出:
|
|
new 与 make 的区别
- 二者都是用来做内存分配的。
make
只用于slice
、map
以及channel
的初始化, 返回的还是这三个引用类型本身。new
用于类型的内存分配, 并且内存对应的值为类型零值, 返回的是指向类型的指针。