Go语言基础
# 第一章:Go语言语法基础
# 1.1 第一个go程序
mkdir hello-go
cd hello-go
go mod init hello-go
2
3
4
5
根目录下创建 mian.go 文件
package main
// 1. 包的声明,声明我们当前的构建程序,属于哪一个包
// 2. package main 表示我们现在定义的包是一个可以执行的程序
// 3. 每个包都包含一个 main.go 文件
import "fmt"
// 1. import 表示导入 ,表示我当前需要使用 fmt 里的一些方法
// 2. fmt 格式化输出包,
// 1. 定义一个 main 函数
// 2. main 函数表明了开始执行函数
// 3. 每一个可执行程序,必须包含一个 main 函数
func main(){
// 这是单行的注释,使用较多
/*
多行注释/ 块注释
*/
fmt.Println("hello go")
}
// 1. go语言的 {} 不能单独放一行,必须放在函数后,或执行语句后
// 2. go语言 一行语句结束了之后,不需要添加 ; 号
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
打开命令行,执行:
go run main.go
# 1.2 go常用命令
# 查看可用命令
直接在终端中输入 go help
即可显示所有的 go
命令以及相应命令功能简介,主要有下面这些:
- build:编译包和依赖
- clean:移除对象文件
- doc:显示包或者符号的文档
- env:打印go的环境信息
- bug:启动报错报告
- fix:运行
gofmt
进行格式化 - generate:从
processing source
生成go
文件 - get:下载并安装包和依赖
- install:编译并安装包和依赖
- list:列出包
- run:编译并运行
go
程序 - test:运行测试
- tool:运行
go
提供的工具 - version:显示
go
的版本 - vet:运行
go tool vet
# 参考文档
https://golang.org/doc/cmd
# 1.3 golang开发 vscode 快捷键
# 快捷键位置
File -> Preferences -> Keyboard Shortcuts
mac
code -> 首选项 -> 键盘快捷方式
# 常用快捷键
1. 行注释 ctrl + /
2. 块注释 shift + alt + a (可以修改为ctrl+shift+/)
3. ctrl + a 全选
4. ctrl + c 复制
5. ctrl + v 粘贴
6. ctrl + shift + k 删除行
7. ctrl + e查找文件
8. ctrl + shift + p 打开设置命令行
2
3
4
5
6
7
8
# 修改快捷键
- 打开快捷键
File -> Preferences -> Keyboard Shortcuts
- 双击要修改的快捷键
- 键盘输入想要使用的快捷键
# 快速生成代码片段
pkgm main包+main主函数
ff fmt.Printf("", var)
for for i := 0; i < count; i++ {}
forr for _, v := range v {}
fmain func main() {}
a.print! fmt.Printf("a: %v\n", a)
2
3
4
5
6
# 1.4 goland标识符、关键字、命名规则
# 标识符
标识符的英文是identifier
,通俗的讲,就是给变量、常量、函数、方法、结构体、数组、切片、接口起名字。
# 标识符的组成
- 标识符由数字、字母和下划线(
_
)组成。123 abc _ - 只能以字母和下划线(
_
)开头。abc123 _sysVar 123abc - 标识符区分大小写。name Name NAME
# 举例说明标识符的命名
# 正确的命名
package main
import "fmt"
func main() {
var name string
var age int
var _sys int
}
2
3
4
5
6
7
8
9
# 错误的标识符
package main
import "fmt"
func main() {
var 1name string
var &age int
var !email
}
2
3
4
5
6
7
8
9
# go语言关键字
go语言提供了25个关键字,如下所示。
break | default | func | interface | select |
---|---|---|---|---|
case | defer | go | map | struct |
chan | else | goto | package | switch |
const | fallthrough | if | range | type |
containue | for | Import | return | Var |
除了以上介绍的这些关键字,Go 语言还有 36 个预定义标识符,其中包含了基本类型的名称和一些基本的内置函数,见下表:
append | bool | byte | cap | close | complex | complex64 | complex128 | uint16 |
---|---|---|---|---|---|---|---|---|
copy | false | float32 | float64 | imag | int | int8 | int16 | uint32 |
int32 | int64 | iota | len | make | new | nil | panic | uint64 |
println | real | recover | string | true | uint | uint8 | uintptr |
# go语言命名规范
# Go是一门区分大小写的语言
命名规则涉及变量、常量、全局函数、结构、接口、方法等的命名。 Go语言从语法层面进行了以下限定:任何需要对外暴露的名字必须以大写字母开头,不需要对外暴露的则应该以小写字母开头。
当命名(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,如:GetUserName
,那么使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出(像面向对象语言中的 public
); 命名如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的(像面向对象语言中的 private
)
# 包名称
保持package
的名字和目录保持一致,尽量采取有意义的包名,简短,有意义,尽量和标准库不要冲突。包名应该为小写单词,不要使用下划线或者混合大小写。
package dao
package service
2
# 文件命名
尽量采取有意义的文件名,简短,有意义,应该为小写单词,使用下划线分隔各个单词。
customer_dao.go
# 结构体命名
采用驼峰命名法,,首字母根据访问控制大写或者小写。
struct
申明和初始化格式采用多行,例如下面:
type CustomerOrder struct {
Name string
Address string
}
order := CustomerOrder{"tom", "北京海淀"}
2
3
4
5
# 接口命名
命名规则基本和上面的结构体类型。
单个函数的结构名以 er 作为后缀,例如 Reader
Writer
type Reader interface {
Read(p []byte) (n int, err error)
}
2
3
# 变量命名
和结构体类似,变量名称一般遵循驼峰法,首字母根据访问控制原则大写或者小写,但遇到特有名词时,需要遵循以下规则:
如果变量为私有,且特有名词为首个单词,则使用小写,如 appService 若变量类型为 bool 类型,则名称应以 Has, Is, Can 或 Allow 开头
var isExist bool
var hasConflict bool
var canManage bool
var allowGitHook bool
2
3
4
# 常量命名
常量均需使用全部大写字母组成,并使用下划线分词
const APP_URL = "https://www.duoke360.com"
如果是枚举类型的常量,需要先创建相应类型:
type Scheme string
const (
HTTP Scheme = "http"
HTTPS Scheme = "https"
)
2
3
4
5
6
# 错误处理
错误处理的原则就是不能丢弃任何有返回err的调用,不要使用 _ 丢弃,必须全部处理。接收到错误,要么返回err,或者使用log记录下来尽早return:一旦有错误发生,马上返回,尽量不要使用panic,除非你知道你在做什么,错误描述如果是英文必须为小写,不需要标点结尾,采用独立的错误流进行处理。
// 错误写法
if err != nil {
// 错误处理
} else {
// 正常代码
}
// 正确写法
if err != nil {
// 错误处理
return // 或者继续
}
// 正常代码
2
3
4
5
6
7
8
9
10
11
12
13
# 单元测试
单元测试文件名命名规范为 example_test.go
测试用例的函数名称必须以 Test
开头,例如:TestExample
每个重要的函数都要首先编写测试用例,测试用例和正规代码一起提交方便进行回归测试 。
# 1.5 goland变量
变量是计算机语言中能储存计算结果或能表示值的抽象概念。不同的变量保存的数据类型可能会不一样。
# 声明变量
Go语言中的变量需要声明后才能使用,同一作用域内不支持重复声明。 并且Go语言的变量声明后必须使用。
# 声明变量的语法
var identifier type
var
:声明变量关键字
identifier
:声明变量关键字
type
:声明变量关键字
# 例如
package main
import "fmt"
func main() {
var name string
var age int
var ok bool
}
2
3
4
5
6
7
8
9
# 批量声明
使用一个var
关键字,把一些变量写在一个括号()
里
package main
func main() {
var (
name string
age int
ok bool
)
}
2
3
4
5
6
7
8
# 变量的初始化
Go语言在声明变量的时候,会自动对变量对应的内存区域进行初始化操作。每个变量会被初始化成其类型的默认值,例如: 整型和浮点型变量的默认值为0
。字符串变量的默认值为空字符串“”
。 布尔型变量默认为false
。 切片、函数、指针变量的默认为nil
。
# 变量初始化语法
var 变量名 类型 = 表达式
# 例如
package main
func main() {
var name string = "老郭"
var site string = "www.duoke360.com"
var age int = 30
}
2
3
4
5
6
# 类型推导
我们在声明变量时,可以根据初始化值进行类型推导,从而省略类型。
package main
func main() {
var name = "老郭"
var site = "www.duoke360.com"
var age = 30
}
2
3
4
5
6
# 初始化多个变量
可以一次初始化多个变量,中间用逗号分隔。
package main
func main() {
var name, site, age = "老郭", "www.duoke360.com", 30
}
2
3
4
# 短变量声明
在函数内部,可以使用:=
运算符对变量进行声明和初始化。
package main
func main() {
name := "老郭"
site := "www.duoke360.com"
age := 20
}
2
3
4
5
6
7
注意:这种方法只适合在函数内部,函数外面不能使用。
# 匿名变量
如果我们接收到多个变量,有一些变量使用不到,可以使用下划线_
表示变量名称,这种变量叫做匿名变量。例如:
package main
import "fmt"
func getNameAndAge() (string, int) {
return "老郭", 30
}
func main() {
name, _ := getNameAndAge()
fmt.Printf("name: %v\n", name)
}
2
3
4
5
6
7
8
9
10
11
12
# 1.6 go语言常量
常量,就是在程序编译阶段就确定下来的值,而程序在运行时则无法改变该值。在Go程序中,常量可以是数值类型(包括整型、浮点型和复数类型)、布尔类型、字符串类型等。
####定义常量的语法
定义一个常量使用const
关键字,语法格式如下:
const constantName [type]= value
const
:声明变量关键字
constantName
:声明变量关键字
type
:声明变量关键字
value
:声明变量关键字
# 实例
package main
func main() {
const PI float64 = 3.14
const PI2 = 3.1415 // 可以省略类型
const (
width = 100
height = 200
)
const i, j = 1, 2 // 多重赋值
const a, b, c = 1, 2, "foo"
}
2
3
4
5
6
7
8
9
10
11
12
13
14
const
同时声明多个常量时,如果省略了值则表示和上面一行的值相同
package main
import "fmt"
func main() {
const (
a1 = 100
a2
a3
)
fmt.Printf("a1: %v\n", a1)
fmt.Printf("a2: %v\n", a2)
fmt.Printf("a3: %v\n", a3)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 运行结果
a1: 100
a2: 100
a3: 100
2
3
# iota
iota 比较特殊,可以被认为是一个可被编译器修改的常量,它默认开始值是0
,每调用一次加1
。遇到 const
关键字时被重置为 0
。
# 实例
package main
import "fmt"
func main() {
const (
a1 = iota
a2 = iota
a3 = iota
)
fmt.Printf("a1: %v\n", a1)
fmt.Printf("a2: %v\n", a2)
fmt.Printf("a3: %v\n", a3)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
运行结果
a1: 0
a2: 1
a3: 2
2
3
使用_
跳过某些值
package main
import "fmt"
func main() {
const (
a1 = iota
_
a2 = iota
)
fmt.Printf("a1: %v\n", a1)
fmt.Printf("a2: %v\n", a2)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
运行结果
a1: 0
a2: 2
2
iota
声明中间插队
package main
import "fmt"
func main() {
const (
a1 = iota
a2 = 100
a3 = iota
)
fmt.Printf("a1: %v\n", a1)
fmt.Printf("a2: %v\n", a2)
fmt.Printf("a3: %v\n", a3)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
运行结果
a1: 0
a2: 100
a3: 2
2
3
# 1.7 go语言数据类型
在Go
编程语言中,数据类型用于声明函数和变量。
数据类型的出现是为了把数据分为所需内存大小不同的数据,编程的时候需要用大数据的时候才需要申请大内存,就可以充分利用内存。
Go 语言按类别有以下几种数据类型:
序号 | 类型和描述 |
---|---|
1 | 布尔型 布尔型的值只可以是常量 true 或者 false。一个简单的例子:var b bool = true。 |
2 | 数字类型 整型 int 和浮点型 float32、float64,Go 语言支持整型和浮点型数字,并且支持复数,其中位的运算采用补码。 |
3 | 字符串类型 字符串就是一串固定长度的字符连接起来的字符序列。Go 的字符串是由单个字节连接起来的。Go 语言的字符串的字节使用 UTF-8 编码标识 Unicode 文本。 |
4 | 派生类型 包括:(a) 指针类型(Pointer)(b) 数组类型(c) 结构化类型(struct)(d) Channel 类型(e) 函数类型(f) 切片类型(g) 接口类型(interface)(h) Map 类型。 |
# 数字类型
Go 也有基于架构的类型,例如:int、uint 和 uintptr。
序号 | 类型和描述 |
---|---|
1 | uint8 无符号 8 位整型 (0 到 255) |
2 | uint16 无符号 16 位整型 (0 到 65535) |
3 | uint32 无符号 32 位整型 (0 到 4294967295) |
4 | uint64 无符号 64 位整型 (0 到 18446744073709551615) |
5 | int8 有符号 8 位整型 (-128 到 127) |
6 | uint16 有符号 16 位整型 (-32768 到 32767) |
7 | uint32 有符号 32 位整型 (-2147483648 到 2147483647) |
8 | uint64 有符号 64 位整型 (-9223372036854775808 到 9223372036854775807) |
# 浮点型
序号 | 类型和描述 |
---|---|
1 | float32 IEEE-754 32位浮点型数 |
2 | float64 IEEE-754 64位浮点型数 |
3 | complex64 32 位实数和虚数 |
4 | complex128 64 位实数和虚数 |
# 其他数字类型
以下列出了其他更多的数字类型:
序号 | 类型和描述 |
---|---|
1 | byte 类似 uint8 |
2 | rune 类似 int32 |
3 | uint 32 或 64 位 |
4 | int 与 uint 一样大小 |
5 | uintptr 无符号整型,用于存放一个指针 |