第一节课:编译
创建文件的时候需要初始化当前目录,那么需要在当前目录执行如下:
1 | go mod init [文件名]/[Github] |
常规编译
1 | go build |
go run不会生成程序,build会。
跨平台编译
直接编译:
1 | go build -ldflags="-s -w " -trimpath |
mac下编译Linux和windows平台64位可执行程序:
1 | CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build |
Linux下编译mac和windows平台64位可执行程序:
1 | CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build |
windows下编译mac和Linux平台64位可执行程序:
1 | SET CGO_ENABLESD=0 |
第二节课:基础语法
- 一行代码标识一条语句的结束后续不需要添加分号。
- 花括号只能是跟在里面用,例如:func main() {
- 变量赋值语句只能写在mian里
- 变量声明没使用也会促发错误
- go里自带自动化格式化代码攻击,仅需执行:go fmt main.go
- 推荐使用驼峰命名法
有意思的问题
1 | 1、fmt.Println()和fmt.Printf()的区别 |
第三节课:变量和常量
标识符
只能以字母数字组成,不能数字开头,只能说是字母或”_”开头。
关键词
在go语言中有25个关键词
1 | break、default、func、interface、select、case、defer、go、map、struct、chan、else、goto、package、switch、const、fallthrough、if、range、type、continue、for、import、returen、var |
此外还有三十七个保留字
变量
标准声明变量格式
1 | var 变量名 变量类型 |
变量声明以关键词var开头,变量类型放在变量的后面,行尾无需分毫,举个例子:
1 | var name string |
批量声明
1 | var( |
示例代码:
1 | package main |
go支持类型推导,也就是会根据你赋值的值然后判断变量的类型,例如如下:
1 | var name = "helloworld"//这个就没写类型,是因为自动进行了类型推导。 |
短变量声明
如下代码,自动声明一个变量,默认值为10
1 | m:=10 |
匿名变量
在使用多重赋值时,如果想要忽略某个值,可以使用“匿名变量(Anonymous variable)”匿名变量用一个下划线_表示,匿名变量不占用命名空间,不会分批内存,不存在重复声明。
_ 多用于占位,表示忽略值。
案例:
1 | package main |
需要注意的是
- 函数外的每个语句都必须以关键词开始(var、const、func等)
- :=不能使用在函数外
- _多用于占位,表示忽略值
常量
相对变量,常量是恒定不变,由关键词var换成了const,在定义的时候必须赋值。多用于配置项,不会变化的值。
和变量一样可以单个生成也可以多个生成
1 | package main |
iota
iota只能在常量表达式中使用,iota遇到const关键词的时候默认值为0,const中每新增一行常量声明将iota计数一次。
举个例子:
1 | package main |
如果要跳过某个值那么可以结合匿名变量。如下所示:
1 | const ( |
iota中间插队
1 | const ( |
第四节课:数据类型
go语言中,数据类型除了基本的整型、浮点型、布尔型、字符串以外还有数组、切片、结构体、函数、map、通道(channel)、等。
整型
进制转换
1 | package main |
主要是记住如下这几个:
1 | %b 表示二进制 |
浮点数
fmt.Pringln(math.MaxFloat32)
fmt.Pringln(math.MaxFloat64)
复数
布尔值
- 默认为false
- 不允许将整型转换为布尔型,例如1不能表示true,0不能表示false
- 布尔值无法参与数值运算,也无法与其他类型进行转换。
字符串转义符
go语言里的字符串内部使用utf-8编码,字符串的值为双引号中的内容,可以在go语言的源码中直接添加非ascii字符串,例如:
1 | s1 := "hello" |
go语言的字符串常见转义符包括回车、换行、但双引号、制表符等,如下表所示:
转义符 | 含义 |
---|---|
\r |
回车符(返回行首) |
\n |
换行符(直接跳到下一行的同列位置) |
\t |
制表符 |
\' |
单引号 |
\" |
双引号 |
\\ |
反斜杠 |
%T | 1 |
多行字符串
1 |
|
字符串常用操作
1 | len 求字符串长度 |
演示代码案例:
1 | func main() { |
byte和runne类型
uint8
类型,或者叫 byte 型,代表了ASCII码
的一个字符。rune
类型,代表一个UTF-8字符
。- Go 使用了特殊的 rune 类型来处理 Unicode,让基于 Unicode 的文本处理更为方便,也可以使用 byte 型进行默认字符串处理,性能和扩展性都有照顾。
1 | func main() { |
第五节课:运算符
Go 语言内置的运算符有:
- 算术运算符
- 关系运算符
- 逻辑运算符
- 位运算符
- 赋值运算符
算术运算符
运算符 | 描述 |
---|---|
+ | 相加 |
- | 相减 |
* | 相乘 |
/ | 相除 |
% | 求余 |
关系运算符
运算符 | 描述 |
---|---|
== | 检查两个值是否相等,如果相等返回 True 否则返回 False。 |
!= | 检查两个值是否不相等,如果不相等返回 True 否则返回 False。 |
> | 检查左边值是否大于右边值,如果是返回 True 否则返回 False。 |
>= | 检查左边值是否大于等于右边值,如果是返回 True 否则返回 False。 |
< | 检查左边值是否小于右边值,如果是返回 True 否则返回 False。 |
<= | 检查左边值是否小于等于右边值,如果是返回 True 否则返回 False。 |
逻辑运算符
运算符 | 描述 |
---|---|
&& | 逻辑 AND 运算符。 如果两边的操作数都是 True,则为 True,否则为 False。 |
|| | 逻辑 OR 运算符。 如果两边的操作数有一个 True,则为 True,否则为 False。 |
! | 逻辑 NOT 运算符。 如果条件为 True,则为 False,否则为 True。 |
位运算符
位运算符对整数在内存中的二进制位进行操作。
运算符 | 描述 |
---|---|
& | 参与运算的两数各对应的二进位相与。 (两位均为1才为1) |
| | 参与运算的两数各对应的二进位相或。 (两位有一个为1就为1) |
^ | 参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。 (两位不一样则为1) |
<< | 左移n位就是乘以2的n次方。 “a<<b”是把a的各二进位全部左移b位,高位丢弃,低位补0。 |
>> | 右移n位就是除以2的n次方。 “a>>b”是把a的各二进位全部右移b位。 |
赋值运算符
运算符 | 描述 |
---|---|
= | 简单的赋值运算符,将一个表达式的值赋给一个左值 |
+= | 相加后再赋值 |
-= | 相减后再赋值 |
*= | 相乘后再赋值 |
/= | 相除后再赋值 |
%= | 求余后再赋值 |
<<= | 左移后赋值 |
>>= | 右移后赋值 |
&= | 按位与后赋值 |
|= | 按位或后赋值 |
^= | 按位异或后赋值 |
第六节课:流程控制语句
if else(分支结构)
1 | if 表达式1 { |
for(循环结构)
1 | for 初始语句;条件表达式;结束语句{ |
1 | package main |
switch case
1 | func switchDemo1() { |
案例:
1 | package main |
第七节课:数组
1 | package main |
第八节课:函数
1 | package main |
匿名函数
顾名思义,就是没有名字的函数,只能调用一次。不占用内存空间。
1 | func test() { |
第九节课:闭包
内部函数引用外部函数的变量就叫闭包
1 | func AddUpper() func(int) int { |
闭包案例:判断是否存在jpg,如果存则直接输出,否则则加上jpg
1 | func makeSuffix() func(string) string { |
第十节课:defer
资源释放,有点像面对对象里的构析方法。
1、先入后出规则(如下代码第二第三行,先入defer栈的是第二行的hello1,然后再是hello2)
2、在return后执行defer
1 | func test(n1, n2 int) int { |
第十一节课:切片
切片与数组
数组是固定长度,可以容纳相同数据类型的元素集合。当长度固定的时候使用带来一些限制,例如:申请长度太大浪费内存,申请太小不够用。
切片长度可变,底层也是基于数组实现的,增加了自动扩容功能。切片(Slice)是一个拥有相同类型元素的可变长度的序列。
切片声明
1 | //格式 |
切片是应用类型,可以使用make函数来创建切片:
1 | var slice1 []type = ([]type,len) |
代码案例:
1 | package main |
切片的添加删除及遍历
1 | // 切片遍历及添加删除 |
第十二节课:map
map是一种key:values
键值对的数据容器,内部实现是hash表,map最重要的是通过key来建立快速索引数据,map是引用类型的。
声明及使用
1 | package main |
map遍历
1 | package main |
第十三节课:init函数
init函数在main函数之前执行,实现包级别的一些初始化操作。
init主要的一些特点
- init函数优于main函数自动执行,不能被其他函数调用;
- init函数没有输入参数、返回值;
- 每个包可以有多个init函数;
- 包的每个源文件也可以有多个init函数,这点比较特殊;
- 同一个包的init执行顺序,golang没有明确定义,编程时要注意程序不要依赖这个执行顺序。
- 不通报的init函数按照包倒入的依赖关系决定执行顺序。
Golang初始化顺序
初始化循序:变量初始化->init()->main()
实例:
1 | package main |