Golang-02:基础知识 & 数据类型详解
1. Go 语言介绍
1.1 Go 语言优势
- 语法简单 - 开发效率高(例如下面短短十行代码就实现了一个简单的 HTTP 服务器)
1 | package main |
集各种语言的优势,有丰富的标准库和完善的工具链:大量参考 c 和 python
- c 语言:静态类型系统、指针操作等特点
- Python 语言:简洁语法、垃圾回收等优势
执行性能高: 直接编译成二进制,部署非常简单
想运行 Python 程序则需要预先安装好 Python
想运行 Java 程序则需要预先安装 jdk
而想运行 go 程序则不用事先安装任何软件,因为它本身就是 exe 文件可以直接执行
并发编程非常高效:goroutine
编译速度快:比 C++、Java 编译快
1.2 Go 语言能做什么?
应用场景
- Web 开发
- gin (ginex)、hertz、beego 等
- 容器虚拟化
- docker、k8s、istio
- 中间件
- etcd、tidb、infuluxdb、nsq 等
- 区块链
- 以太坊、fabric
- 微服务
- kitex、go-zero、dapr、rpcx、kratos、dubbo-go
使用情况
- 国内使用热度超过国外
- 大量国内公司使用
- 字节跳动、百度、腾讯、阿里、B 站、小米、滴滴、京东、360、七牛云、知乎、美团、OPPO 等
使用原因
- 最初使用的 Python,由于性能问题换成了 Go
- Python 是一种解释型语言。解释型语言在运行时需要解释器将代码翻译成机器语言,因此其执行速度相对较慢。
- Go 是一种编译型语言。而编译型语言则直接将代码编译成机器语言,执行速度相对较快。
- C++ 不太适合在线 Web 业务
- 早期团队非 Java 背景
- 性能比较好
- 部署简单,学习成本低
- 内部 RPC 和 HTTP 框架的推广
1.3 开发环境
入门配置教程:Golang-01:如何快速运行 Golang 程序
1.3.1 安装 Golang
直接打开浏览器输入 go.dev 网址进行下载即可。
如果打不开的话可以尝试使用 Golang 中国的 studygolang 镜像。
另外,如果访问 github 的速度非常慢的话,可以配置 go mod proxy,打开下面的网页按照提示操作即可,配置完成后下载第三方包的速度会大大加快。
1.3.2 配置开发环境
常用的 Golang 编辑器 / IDE 有两个,我一般会更习惯 Goland 进行开发~
- vscode
vscode 是一款由微软开发的,能运行在 Mac、Windows 和 Linux 上的跨平台开源代码编辑器。它可以通过扩展程序为编辑器实现代码高亮、代码提示编译调试、文档生成等功能,配置完成后可以视为一个齐全的 IDE。
- Goland
Goland 是由 JetBrains 公司开发的一个新的商业 IDE,相比 vscode,它在重构、代码生成等方面做的更好。Goland 是一个收费软件,我们可以直接从官网下载,然后可以 30 天免费试用。
2. 变量与常量
2.1 定义与使用
2.1.1 命名规则
- 一个名字必须以一个字母(Unicode 字母)或下划线开头,后面可以跟任意数量的字母、数字或下划线
- 大写字母和小写字母是不同的:heapSort 和 Heapsort 是两个不同的名字
- Go 语言程序员推荐使用驼峰式命名,当名字由几个单词组成时优先使用大小写分隔,而不是优先用下划线分隔
- 像 ASCII 和 HTML 这样的缩略词则避免使用大小写混合的写法,它们可能被称为 htmlEscape、HTMLEscape 或 escapeHTML,但不会是 escapeHtm
- Go 语言中类似 if 和 switch 的关键字有 25 个;关键字不能用于自定义名字,只能在特定语法结构中使用
1 | break default func interface select |
变量名可见性
- 如果一个名字是在函数内部定义,那么它就只在函数内部有效。如果是在函数外部定义,那么将在当前包的所有文件中都可以访问。
- 名字的开头字母的大小写决定了名字在包外的可见性。如果一个名字是大写字母开头的,那么它将是导出的,也就是说可以被外部的包访问,例如 fmt 包的 Printf 函数就是导出的,可以在 fmt 包外部访问。
- 包本身的名字一般总是用小写字母。
2.1.2 如何定义变量?
- 变量必须先定义才能使用
- go 语言是静态语言,要求变量的类型和赋值类型一致
- 变量名不能冲突
- 简洁变量定义不能用于全局变量
- 变量是有零值,也就是默认值
- 定义了变量一定要使用,否则会报错
下面声明变量的方式都等价:实践中一般使用前两种形式中的某个,初始值重要的话就显式地指定变量的值,否则指定类型使用隐式初始化。
- 第一种形式,是一条短变量声明,最简洁,但只能用在函数内部,而不能用于包变量。
- 第二种形式依赖于字符串的默认初始化零值机制,被初始化为
""。 - 第三种形式用得很少,除非同时声明多个变量。
- 第四种形式显式地标明变量的类型,当变量类型与初值类型相同时,类型冗余,但如果两者类型不同,变量类型就必须了。
1 | // 方法一 |
注意:
自增语句
i++给i加1;这和i+=1以及i=i+1都是等价的。对应的还有i--给i减1。它们是语句,而不像 C 系的其它语言那样是表达式。所以j=i++非法,而且++和--都只能放在变量名后面,因此--i也非法。
2.1.3 常量定义须知
- 常量定义的时候指定的值不能修改,常量尽量大写
- 常量类型只可以定义 bool、数值(整数、浮点数和复数)和字符串
- 不曾使用的常量,没有强制使用的要求
- 显示指定类型的时候,必须确保常量左右值类型一致
- 同时定义多个常量时,需要注意未指明的常量将引用前面定义的值:
1 | const ( |
2.2 Iota 的使用细节
iota,特殊常量,可以认为是一个可以被编译器修改的常量。
1 | const( |
注意:
- 如果中断了 iota,那么必须显示的恢复,后续会自动递增
- 自增类型默认是 int 类型
- iota 能简化 const 类型的定义
- 每次出现 const 的时候,iota 初始化为 0
2.3 匿名变量的定义与使用
匿名变量是一种特殊的变量,使用 _ 表示,它只占位不存储值,可用于忽略函数返回值中不需要的部分,或者在多重赋值中丢弃不需要的变量。
1 | //匿名变量 |
3. Go 基本数据类型
3.1 Bool 类型
布尔类型的值只可以是常量 true 或者 false,比如:var b bool = true。
3.2 数值类型
注意:
byte 和 rune 主要是用于存储字符,byte 存储的范围更小,rune 存储的范围更大,可以包括中文。
3.3 String 类型
3.3.1 底层存储原理
1 | var str string = "hello" |
go 语言和 c 语言对于字符串结尾的判定条件有所不同,c 语言会认为在结尾处加上 \0 就代表这个字符串的结束。但是这就会限制内容中不能再出现 \0,如果出现就会发生不可预估的后果。
因此,在 go 语言中并没有采用这种方式,而是在起始地址后边,多存了一个长度。
注意:
在起始地址后存的长度并不是表示字符个数,而是表示字节个数。
3.3.2 常用操作
1 | package main |
3.3.3 数字解析
在 go 语言中,关于字符串和数字类型之间的转换的函数都在 strconv 这个包下。
1 | package main |
3.3.4 格式化输出
注意:
以字母
f结尾的格式化函数,如log.Printf和fmt.Errorf,都采用fmt.Printf的格式化准则。而以ln结尾的格式化函数,则遵循Println的方式,以跟%v差不多的方式格式化参数,并在最后添加一个换行符(译注:后缀f指format,ln指line)。
- 缺省格式和类型
| 格式化后的效果 | 动词 | 描述 |
|---|---|---|
| [0 1] | %v |
缺省格式 |
| []int64{0, 1} | %#v |
go 语法打印 |
| []int64 | %T |
类型打印 |
- 整形(缩进、进制类型、正负符号)
| 格式化后的效果 | 动词 | 描述 |
|---|---|---|
| 15 | %d |
十进制 |
| +15 | %+d |
必须显示正负符号 |
| __15 | %4d |
Pad 空格 (宽度为 4,右对齐) |
| 15__ | %-4d |
Pad 空格 (宽度为 4,左对齐) |
| 1111 | %b |
二进制 |
| 17 | %o |
八进制 |
| f | %x |
16 进制,小写 |
- 字符(有引号、Unicode)
Value:65(Unicode letter A)
| 格式化后的效果 | 动词 | 描述 |
|---|---|---|
| A | %c |
字符 |
| ‘A’ | %q |
有引号的字符 |
| U+0041 | %U |
Unicode |
| U+0041 ‘A’ | %#U |
Unicode 有引号 |
- 浮点(缩进、精度、科学计数)
Value:123.456
| 格式化后的效果 | 动词 | 描述 |
|---|---|---|
| 1.234560e+02 | %e |
科学计数 |
| 123.456000 | %f |
十进制 |
- 字符串/字节 silce(引号、缩进、16 进制)
Value:"cafe"
| 格式化后的效果 | 动词 | 描述 |
|---|---|---|
| cafe | %s |
字符串原样输出 |
| __cafe | %6s |
宽度为 6,右对齐 |
- 案例
1 | package main |
3.3.5 只读特性
下标访问字符串:
1 | str := "golang" |
注意:
go 语言中不能用下标直接去修改字符串内容,但是可以用来访问。
原因是 go 认为上面这样的字符串是不会被修改的,所以会把这样定义的字符串内容分配到只读内存段。
如果想修改字符串内容的话,可以转化成 slice,但是可能会同时修改底层字符串的内容。
如果想脱离这个只读的限制,并且想修改时不会影响到底层字符串的内容。那么可以转换成字节 slice,这样就会为 slice 变量重新分配一段内存,同时会也会拷贝原来字符串的内容。
1 | byteStr := ([]byte)(s1) |
举个具体点的例子:
1 | package main |
3.3.6 高性能字符串拼接
1 | username := "张三" |
性能要求不高,平时一般采用:
1 | userMsg := fmt.Sprinf("用户名:%s,年龄:%d,地址:%s,电话:%s", username, age, address, mobile) |
性能要求高:
1 | var builder string.Builder |






