一、语法基础
1.Go文件布局
1).package子句
2).任何import语句
3).实际代码
2.Go是静态类型的,这意味着它甚至在程序运行之前就知道值的类型是什么
3.reflect包的TypeOf函数用来查看值的类型
4.声明变量:var 变量名 变量类型 = 变量的值
5.短变量声明:变量名 := 变量的值
6.命名规则:名称必须以字母开头,如果名称以大写字母开头,则认为它是导出的,可以从当前包之外的包访问它;如果名称以小写字母开头,则认为该名称是未导出的,只能在当前包中使用
7.类型转换:转换的类型(转换的值)
二、条件和循环
1.方法是与特定类型的值关联的函数
2.strings包有一个Replacer类型,可以进行字符串的替换
3.调用方法的格式:值.方法名;例如now.Year();其中now保存time.Time的值,Year()对time.Time值调用Year方法
4.从键盘输入的内容是作为字符串读入的,而且输入字符串的末尾仍然有一个换行符
5.srings包有个TrimSpace函数,它将删除字符串开头和结尾的所有空白字符
6.strconv包的ParseFloat函数可以将用户输入的数字字符串转换为float64的值
7.nil代表是无值
8.要使用空白标识符,只需在赋值语句中输入一个下划线(_)字符
9.log包有一个Fatal函数,可以同时为我们完成将一条信息记录到终端并停止程序运行
10.变量的作用域由其声明所在块和嵌套在该块中的任何块组成
三、函数
1.函数定义:func 函数名(参数名,参数类型) { }
2.math/rand包有一个Intn函数,可以生成一个随机数
3.为了得到不同的随机数,需要向rand.Seed函数传递一个值
4.fmt包提供了Printf函数,Printf代表带格式的打印
5.Sprintf函数与Printf函数类似,只是它返回格式化的字符串而不是打印它
6.%5.3f中%代表格式化动词开始,5代表整个数的最小宽度,3代表小数点后的宽度,f代表格式化动词类型
7.名称以大写字母开头的函数是可导出,并且可以在当前包之外使用。小写字母开头的函数表示只能在当前包中使用
8.当return语句运行时,函数立即退出,而不运行他以后的任何代码
9.strconv.Atoi函数是将字符串转化为整数
10.创建错误值的最简单方法是将字符串传递给errors包的New函数,该函数将返回一个新的错误值
11.函数形参接收的是实参的副本(值传递)
12.*int:指向一个int变量的指针的类型
13.可以从函数返回指针,只需声明函数的返回类型是指针类型
14.不能在函数的外部访问在该函数内声明的变量;但是你可以在函数内访问在该函数外部声明的变量
四、包
1.如果你的部分代码在多个程序之间共享,你应该考虑将它们移到包中
2.按照惯例,包的目录应该与包同名,但是main包是个例外
3.需要用其他包中的函数则需要用到import导入相应的包(自定义的包)
4.包名应全部为小写
5.当访问从不同包导出的函数、变量时,需要通过在函数、变量前面输入包名来限定它们的名称;但是当访问定义在当前包中的函数或变量时,这不应该限定包名
6.将共享的代码移动到包中以方便其他程序使用该包
7.常量的声明:使用const关键字且必须在声明时赋值
8.与变量和函数一样,名称以大写字母开头的常量是可导出的
9.go工具还有一个名为go get的子命令,它可以自动为你下载和安装包
10.Go在工作区中使用三个子目录:bin目录保存编译过的可执行程序;pkg目录保存编译过的包代码;src目录保存Go源代码
五、数组
1.数组是所有共享同一类型的值的集合
2.字符串的零值是空字符串
3.数组的初始化可以使用:=短变量声明
4.安全遍历数组:for index, value := range array{ },忽略index的话可以使用空白标识符(_)
5.os.Open(“file”):打开文件;bufio.NewScanner(file):为文件创建一个新的扫描器
6.Go数组的大小是固定的,它们不能增长或收缩
六、切片
1.切片是一个可以通过增长来保存额外数据的集合类型
2.声明一个保存切片的变量:var 变量名 [ ]元素类型
3.声明切片变量并不会自动创建一个切片,需要调用make函数:变量名 = make([ ]元素类型,元素个数)
4.可以使用短变量声明创建切片:变量名 := make([ ]元素类型,元素个数)
5.可以自己创建一个数组,然后再基于数组通过切片运算符创建一个切片
6.切片并不会自己保存任何数据,它仅仅是底层数组的元素的视图;所以修改底层数组,这些变化也会反映到切片
7.使用make和切片字面量,就不用关心底层数组
8.Go的内建函数append可以在切片末尾添加元素,但是需要确保将append返回的值重新赋给传递给append的那个变量
9.为了让函数的参数可变长,在函数声明中的最后的参数类型前使用省略号(...)
10.仅仅函数定义中的最后一个参数可以是变长参数,不能放在必须参数之前
11.当我们调用一个可变长参数函数时,简单地在传入的切片变量后增加省略号(...)即可
12.os.Args包变量包含当前程序执行的命令行参数组成的string类型的切片
七、映射
1.计算名字出现了多少次:i.创建两个切片分别保存名字和出现次数 ii.映射
2.一个映射是通过一个键来访问每一个值的集合,映射可以使用任意类型的键
3.声明保存映射的变量:var 变量名 map[键类型]值类型
4.声明一个映射变量并不会自动创建一个映射,需要调用make函数
5.可以使用短变量声明
6.可以使用字面量来创建映射:变量名 := map[键类型]值类型{键:值,键:值}
7.如何区分一个键是被赋值为零值还是未赋值:访问键的时候获取第二个布尔类型的值
8.删除键值对:使用delete函数,delete(映射的变量名,键)
9.对映射进行for...range循环:for 键, 值 := range 映射的变量名;但是这是以随机的顺序处理映射,如果需要按照某种顺序输出,则需要循环遍历映射中所有的键,忽略值,并且把它们append到一个字符串切片 中,然后使用sort.Strings(切片变量名)来以字母表顺序排序
10.循环所有的键时,可以忽略对应的值变量:for 键 := range 映射的变量名
11.循环所有的值时,需要将键写成空白标识符(_):for _, 值 := range 映射的变量名
八、结构
1.声明一个结构类型:struct{
字段1名称:字段1类型
字段2名称:字段2类型
}
2.定义struct变量:var 结构变量名 struct{
字段1名称:字段1类型
字段2名称:字段2类型
}
3.点运算符:i.表示函数属于一个包 ii.表示方法属于一个值 iii.表示字段属于一个结构
4.自定义类型:type 类型名 基础类型名{ }
5.使用点运算符在struct指针和struct上都可访问字段
6.访问struct的字段需要使用括号包裹(*struct指针):(*struct指针).字段
7.可以使用括号和*运算符,而使用struct指针来访问字段:struct指针.字段
8.函数形参接收一个函数调用的实参的拷贝,即使是struct也是如此,因此如果传递一个有很多字段的大的struct就会占用很多内存,所以除非struct只有很少的字段,否则向函数传入struct的指针就不会产生一个额外的拷贝
9.定义类型的名称首字母必须大写才能导出该类型
10.struct字段的名称首字母必须大写才能导出该字段
11.Go提供了struct字面量来让你创建一个struct并同时给它的字段赋值
12.struct可以嵌套struct
13.匿名struct字段:struct字段没有名字,仅仅有类型;使得访问内部struct更加简单
九、定义类型
1.当获得一个数字,我们无法确认单位是什么?这时需要自定义基于基础类型的能表示单位意思的新类型,例如type Liters float64,一旦定义了新类型,就可以从相同基础类型转换成新类型,例如Liters(240.0)
2.可以使用短变量声明(包含类型转换):变量名 := Liters(240.0)
3.单位之间的转换:Gallons(Liters(40.0) * 0.264),将升转换为加仑
4.定义类型不能用来与不同类型的值一起运算,即便它们是来自相同的基础类型
5.可以使用函数进行类型转换
6.定义方法:func (接收器参数名 接收器参数类型) 方法名(参数名,参数类型) { }
7.除了方法在接收器上被调用外,方法与函数完全相同
8.一旦方法定义了某个类型,它就能被该类型的任何值调用
9.Go开发者通常使用一个字母作为名称,即小写的接收器类型名称的首字母
10.Go使用接收器参数来代替其他语言中的self或者this
11.方法名称以大写字母开头,则认为是可导出的
12.不同于函数,只要方法定义在不同的类型中,他们就可以重名
十、封装和嵌入
1.Go语言的getter方法不需要Get前缀
2.setter方法:用来设置字段或者基础类型中的其它值的方法;setter方法通常包含校验逻辑,以确保提供的值是合法的
3.保护字段,使得只能通过setter方法来更新字段的方式:将定义类型移到另一个包中,并且将它的字段设置为未导出的,然后通过相同包中导出的方法访问。
4.getter方法:获取struct字段或者变量的值的方法
5.封装:将程序中的数据隐藏在一部分代码中而对另一部分不可见的方法;封装可以被用来保护数据免于无效数据
6.Java的类与Go的类型概念相似,但不完全相同
7.Go使用未导出的变量、struct字段、函数或者方法,把数据封装在包中
8.嵌入:一个类型使用匿名字段的方式保存到另一个struct类型中,被称为嵌入了struct;嵌入类型的方法会提升到外部类型;但是一个嵌入类型的未导出方法不会被提升到外部类型;未导出的字段也不会被提升
十一、接口
1.接口:程序提供的用来交互的控制方法;一个接口是特定值预期具有的一组方法
2.定义接口:type 接口类型名 interface {
方法名(参数类型) 返回值类型
}
3.如果一个类型包含接口中声明的所有方法,那么它可以在任何需要接口的地方使用
4.一旦给一个接口类型的变量赋值,就只能调用接口定义的方法
5.实现了接口方法的不同类型的变量,可以给一个接口类型的变量赋值,然后接口类型的变量调用的方法是根据给接口变量赋值的变量类型来确定,即同一个接口实现了不同类型的同名方法
6.接口实际上就是一种协议,不管什么类型,只要传给接口,接口就会调用自己声明的方法,只是根据传进来的类型不同,会有同一方法的不同表现,例如定义一个USB接口,只要你满足USB接口的方法,不管你是什么类型,都可以插进来,接口会根据插进来的类型来使用相应的方法(同一方法的不同表现)
7.接口的作用:接口类型的变量能够存储所有实现了该接口方法的类型的变量