词法单元
关键字
- package、import、func…
标识符
- main、fmt、Printf…
字面量
- 整型宇面 Cinteger literals)
- 浮点型字面量( loating-point literals)
- 复数类型字面量 Cl ma inary literals)
- 字符型字面量( Run literals)
- 字符串字面量 in Ii terals)
函数
函数原型
func funcName (param-list) (result- list) {
function - body
}
支持有名的函数返回值,参数名就相当于函数体内最外层的局部变 命名返回值变量会被初始化为类型零值,最后的 return 可以不带参数名直接返回。
不支持默认值
- 考虑使用闭包的方式实现默认参数
不支持重载
不支持嵌套
支持多值返回
实参到形参永远是值拷贝
支持不定参数
- 不定参数必须类型相同
- 必须是函数最后一个参数
- 在函数体内,对切片的操作同样适用于不定参数
- 切片加 … 后可以作为参数传给不定参数
- 形参为不定参数 和 形参为切片的 函数类型不相同
函数签名
- 函数类型又叫函数签名
- 函数定义首行去掉函数名、参数名和{
- 相同函数类型 , 如
func add(a,b int) int { return a+b)
func sub (x int, y int) (c int) { c=x- y ; return c ) - type定义函数类型,如
type Op func(int , int) int - Go 中函数是“第一公民 func class )。有名函数的函数名可以看作函数类型的常量
匿名函数
- 匿名函数可以看作函数字面量 所有直接使用函
数类型变量的地方都可以由匿名函数代替。 - 医名函数可以直接赋值给函数变量,可以当作实参,
可以作为返回值,还可以直接被调用
defer
- 以先进后出(FILO )的
顺序在函数返回前被执行 - 最好不要对有名返回值参数进行操作
defer和命名返回值
https://www.yuque.com/docs/share/33e277df-0a28-4126-94c4-573d1f3dabcb
闭包
-
函数中引用外部函数的局部变量或者全局变量
-
函数返回的闭包引用了函数的局部变量或者参数
- 每次调用都返回的该闭包的副本
- 用同一个闭包多次,每次调用都会外部变量有影响,闭包函数共享外部引用
-
价值:对象是附有行为的数据,闭包是附有数据的行为
panic和recover
- defer func() {
println defer nner
recover()
} ) - 可以有连续多个 panic 被抛出,连续多个 panic 场景只会出现在延迟调用里面,只有最后 pani 能被捕获
错误和异常
-
原则
- (1 )程序发生的错误导致程序不能容错继续执行,此时程序应该主动调用 panic 或由运行
时抛出 panic - (2 )程序虽然发生错误 但是程序能够容错继续执行,此时应该使用错误返回值的方式处
理错误,或者在可能发生运行时错误的非关键分支上使用 recover 捕获 panic
- (1 )程序发生的错误导致程序不能容错继续执行,此时程序应该主动调用 panic 或由运行
类型系统
类型
-
命名类型
-
类型可以通过标识符来表示,这种类型称为命名类型。
- Go 语言的基本类型中有 个预声
明简单类型都是命名类型, - 用户自定义类型
- Go 语言的基本类型中有 个预声
-
-
未命名类型
-
一个类型由预声明类型、关键字和操作符组合而成
- Go 语言的基本类型中的复合类型:数组( array )、 -切片(slice )、 字典( map )、通道( channel )、
指针(pointer 函数字面量( func ti )、结构( struct )和接口( interface 〕都属于类型字面量,
也都是未命名类型
- Go 语言的基本类型中的复合类型:数组( array )、 -切片(slice )、 字典( map )、通道( channel )、
-
类型相同
- 两个命名类型相同的条件是两个类型声明的语句完全相同。
- 命名类型和未命名类型永远不相同。
- 两个未命名类型相同的条件是它们的类型声明宇面量的结构相同,井且内部元素的类型相同。
- 通过类型别名语句声明的两个类型相同。
类型别名
- type Tl = T2, Tl 的类型完全和 T2 一样。
- https://hao.io/2018/01/golang-type-aliases/
- 作用
- 为了解决新旧包的迁移兼容问题,比如 context 包先前并不在标准库里面,后面迁移到了标准库
- Go 的按包进行隔离的机制不太精细,有时我们需要将大包划分为几个小包进行开发,在大包里面暴露全部的类型给使用者
- 解决新旧类型的迁移 问题, 新类型先是 类型 的别名,后续的软件都基于新类型编程,在合适的时间将新类型升级为和旧类型不兼容 常用于软件的柔性升级
类型赋值
-
条件
变量a的类型为T1
var b T2 = a- Tl T2 类型相同。
- Tl T2 具有相同的底层类型,并且 Tl T2 里面至少有一个是未命名类型。
- T2 接口类型, Tl 是具体类型, Tl 方法集是 T2 方法集的超集
- Tl T2 是通道类型,它们拥有相同的元素类型,并且 Tl T2 至少有 个是
未命名类型 - 是预声明标识符 nil. T2 pointer funcition slice map channel interface 类型
中的一个 - 是一个字面常量值,可以用来表示类型 的值
类型强制转换
-
语法格式
- 强制类型的语法格式:
var a T = (T) (b )
- 强制类型的语法格式:
-
条件
- 可以直接赋值给T类型变量。
- x 的类型和T具有相同的底层类型
- x的类型和 T都是未命名的指针类型,并且指针指向的类型具有相同的底层类型
- x的类型和 T都是整型,或者都是浮点型
- x的类型和 T都是复数类型
- x是整数值或口byte 类型的值,T是string 类型。
- x是一个字符串,[]byte[] rune
自定义类型
-
type newtype oldtype
- type INT lηt //INT 个使用预声明类型声明的自定义类型
type Map map[string]str ng //Ma 个使用类型字面量声明的自定义类型
type myMap Map //myMap 个自定义类型 Map 声明的自定义类型
I /INT, Map myMap 都是命名类型
- type INT lηt //INT 个使用预声明类型声明的自定义类型
-
type Person struct {
name string
age int
}-
初始化
- a := Person {"andes ”, 18}
- a : = Person{"ηame andes ”, age 18}
- p :=new(Person)
- p := Person{}
p.name =”andes”
p.age = 18
-
-
匿名字段
-
自定义接口
方法
-
类别
-
类型方法接收者是值类型
- func (t TypeName) MethodName (ParamList ) (Returnlist) {
}
- func (t TypeName) MethodName (ParamList ) (Returnlist) {
-
类型方法接收者是指针
- func (t *TypeName) MethodName (ParamList) (Returnlist) {
}
- func (t *TypeName) MethodName (ParamList) (Returnlist) {
-
-
特点
- 可以为命名类型增加方法(除了接口),非命名类型不能自定义方法
- 为类型增加方法有1个限制,就是方法的定义必须和类型的定义在同一个包中
- 方法的命名空间的可见性和变 一样,大写开头的方法可以在包外被访问,否则只能
在包内可见。 - 使 type 定义 自定义类型是一 新类型,新类型不能调用原有类型的方法,但是
底层类型支持的运算可以被新类型继承
-
调用
- TypeinstanceName .MethodName(ParamList)
-
方法值
- 变量x的静态类型是 T. M是类型T的一个方法, x.M被称为方法值
- f : = x . M
f (args … . )
-
方法集
-
将接收者( receiver )为值类型T的方法的集合记录为S,
将接收者( receiver) 为指针类型T的方法的集合统称为S。- T类型的方法集是S
- T类型的方法集是S和S
-
-
组合
-
内嵌字段的访问和初始化
-
内嵌字段的方法调用
- 简写模式下, Go 编译器
优先从外向内逐层查找方法,同名方法中外层的方法能够覆盖内层的方法
- 简写模式下, Go 编译器
-
组合的方法集
- 若类型S包含匿名字段T ,则S的方法集包含T的方法集
- 若类型S包含匿名字段T,则S的方法集包含T和*T方法集。
- 不管类型S中嵌入的匿名字段是T还是*T, S方法集总是包含T和T方法集
-
函数变量
-
函数字面量类型
未命名类型- func(InputTypeList)OutputTypeList
-
函数命名类型
- type NewFuncType FuncL teral
-
函数签名
- 函数签名是函数的“宇量类型”,不包括函数名
-
函数声明
- //函数声明 函数名+函数签名
//函数签名
func (InputTypeList)OutputTypeList
//函数声明
func FuncName (InputTypeList)OutputTypeList
- //函数声明 函数名+函数签名
内容参考:
Go语言核心编程
Go语言圣经