【笔记】Go语言学习笔记

前言

Go(又称Golang)是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。(维基百科

编译器

查看Go环境

1
go env

编译并运行源码

<file>.go:Go语言源代码文件,如果省略,go会自动寻找当前目录下所有go源码进行编译

1
go run <file>.go

编译源码为可执行文件

<file>.go:Go语言源代码文件,如果省略,go会自动寻找当前目录下所有go源码进行编译

-o <file_out>:指定输出的可执行文件存放路径

1
go build <file>.go
  • 编译后会产生可执行文件,Linux/MacOS可执行文件为<file_name>,Windows可执行文件为<file_name>.exe

初始化Go项目

新建主模块

  • 新建一个目录用于存放Go项目,并初始化项目,作为主模块
  • main()主函数是程序的入口,一个程序有且只有一个主函数
1
2
3
mkdir <project_name>
cd <project_name>
go mod init <project_name>
<project_name>/main.go
1
2
3
4
5
package main

func main() {
...
}

创建子模块

<project_name>/app/app.go
1
2
3
4
5
package app

func App() {
...
}

注释

1
// 单行注释
1
/* 多行注释 */

语句分隔符

  • 每行代码末尾无需使用;
1
2
语句
语句
  • 多行代码写作一行时,语句与语句之间必须使用;作为语句分隔符
1
语句;语句

输出语句

带换行的输出语句

1
fmt.Println("文本内容")

输出数据类型

1
fmt.Println(reflect("文本内容"))

不带换行的输出语句

1
fmt.Print("文本内容")

格式化输出

1
fmt.Printf("文本内容%d", 1) // "文本内容1"
格式说明符 数据类型 描述
%v 任何类型 默认格式输出值,对于结构体,输出字段值
%+v 任何类型 默认格式输出值,对于结构体,输出字段名和值
%#v 任何类型 默认格式输出值,对于结构体,输出字段名和值,并且对于基本类型,输出Go语法表示
%d Int 十进制整型数据
%3d Int 十进制整型数据,如果不满足3位,用空格补齐空位,从前面补齐
%-3d Int 十进制整型数据,如果不满足3位,用空格补齐空位,从后面补齐
%03d Int 十进制整型数据,如果不满足3位,用0补齐空位,从前面补齐
%-03d Int 十进制整型数据,如果不满足3位,用0补齐空位,从后面补齐
%b Int 二进制整型数据
%o Int 八进制整型数据
%x Int 十六进制整型数据,字母小写
%X Int 十六进制整型数据,字母大写
%f Float 浮点型数据,默认保留6位小数,自动四舍五入
%.3f Float 浮点型数据,保留小数点后3位小数,自动四舍五入
%t Bool 布尔型数据
%c Char 字符型数据
%s String 字符串型数据
%q String 字符串型数据,输出Go语法表示
%p interface{} 十六进制指针数据
%% - 输出一个百分号

输出数据的类型

1
fmt.Printf("%T", 变量名)

格式化拼接字符串

  • 将格式化后的字符串作为返回值赋值给变量
1
str := fmt.Sprintf("%d", 变量名)

输入语句

  • 如果指定接收数据的类型是整型,那么从获取的字符串开始,一直截取到第一次遇到非数字字符之前结束,如果没有数字,则为0
  • 如果指定接收数据的类型是字符串,那么从获取的字符串开始,一直截取到第一次遇到非空格字符之前结束
  • 如果指定接收数据的类型是整型,且对于接收的变量移除,最终变量得到的结果为0

接收单个字符串

1
2
var 变量名 数据类型
fmt.Scan(&变量名)

接收多个字符串

  • 多组数据通过空白字符分隔
1
2
3
var 变量名1 数据类型
var 变量名2 数据类型
fmt.Scan(&变量名1, &变量名2)
  • 在输入换行符的时候,立即结束输入的接收
1
2
3
var 变量名1 数据类型
var 变量名2 数据类型
fmt.Scanln(&变量名1, &变量名2)
  • 格式化输入
1
2
var 变量名 数据类型
fmt.Scanf("%d", &变量名)

变量

  • 命名规则

    • 变量名由数字、字母、下划线组成
    • 变量名只能以字母、下划线开头
    • 变量名区分大小写
    • 不能使用关键字作为变量名
  • Go命名规范

    • Go中所有命名区分大小写
    • 任何需要对外暴露的名称都需要首字母大写,不需要对外暴露的名称都需要首字母小写
    • 包命名规则:保持package包名称定义与目录名相同
    • 文件命名规则:所有单词小写,使用下划线分割各个单词
    • 结构体命名规则:首字母大写,采用驼峰命名
    • 接口命名规则:首字母大写,采用驼峰命名,以er结尾
    • 变量命名规则:首字母小写,采用驼峰命名
    • 常量命名规则:所有单词大写,使用下划线分割各个单词
    • 单元测试命名规则
      • 单元测试的文件名命名规则:所有单词小写,使用下划线分割各个单词,最后一个单词以test结尾
      • 单元测试的函数名命名规则:首字母大写,采用驼峰命名,第一个单词以Test开头

声明变量

  • 通过var关键字定义一个变量
1
var 变量名 数据类型
1
2
3
4
var (
变量名 数据类型
变量名 数据类型
)

定义变量

1
var 变量名 数据类型 = 值
  • 自动类型推导
1
var 变量名 = 值
  • 短变量
    • 短变量只能声明时立即赋值,不能用作赋值
    • 短变量声明会自动类型推导
    • 短变量声明的变量只能在函数内部声明和使用
    • 短变量声明不需要var关键字和数据类型
1
变量名 := 值

批量定义变量

1
var 变量名1 数据类型, 变量名2 数据类型 = 值, 值
1
2
3
4
var (
变量名 数据类型 = 值
变量名 数据类型 = 值
)
  • 自动类型推导
1
var 变量名1, 变量名2 = 值, 值
1
2
3
4
var (
变量名 = 值
变量名 = 值
)
  • 短变量
1
变量名1, 变量名2 := 值, 值

变量赋值

  • Go中声明局部变量后必须使用,否则会编译不通过
1
变量名 = 变量值
1
变量名1, 变量名2 = 值, 值

交换变量的值

1
变量名1, 变量名2 = 变量名2, 变量名1

匿名变量

  • 在函数返回值只指定返回值类型而不指定变量名,此时的变量是一个匿名变量
1
2
3
func 函数名() (string) {
return ""
}
  • 如果一个变量不被使用,为了防止报错也可以使用匿名变量进行定义
1
_ := 变量值

常量

定义一个常量

  • Go语言的常量必须在定义时直接赋值,不能先声明再赋值

  • Go语言的常量的数据类型只能是string、int、float、bool类型

1
const 常量名 数据类型 = 常量值
  • 自动类型推导
1
const 常量名 = 常量值

批量定义常量

1
const 常量名1, 常量名2 = 常量值1, 常量值2
1
2
3
4
const (
常量名1 = 常量值1
常量名2 = 常量值2
)
  • 如果多个常量的常量值相同,可以省略常量值,表示常量值与上一行相同
1
2
3
4
const (
常量名1 = 常量值1
常量名2
)

iota枚举

  • iota关键字是一个特殊的常量值,初始值是0,每次被赋值,都会自增1
1
2
3
4
5
const (
常量名 = iota // 0
常量名 = iota // 1
常量名 = iota // 2
)
  • 简写,如果定义常量时省略了赋值,将会自动与上一次赋值相同(iota的值会自增)
1
2
3
4
5
const (
常量名 = iota // 0
常量名 // 1
常量名 // 2
)
  • 在同一行定义的常量,iota的值相同
1
2
3
4
5
const (
常量名 = iota // 0
常量名, 常量名 = iota, iota // 1
常量名, 常量名 // 2
)
  • 如果想跳过当前值,可以使用匿名接收,以达到跳过常量值的效果
1
2
3
4
5
const (
常量名 = iota // 0
_ = iota // 1
常量名 = iota // 2
)
  • 如果在使用iota作为常量值的期间有其他常量值被赋值,此时也会达到跳过常量值的效果
1
2
3
4
5
const (
常量名 = iota // 0
常量名 = 值 // 值
常量名 = iota // 2
)

重置

  • 遇到const关键字时,iota的值重置为0
1
2
3
4
5
const (
常量名 = iota // 0
常量名 = iota // 1
)
const 常量名 = iota // 0

数据类型

数值型

整型

  • 默认值为0
1
var 变量名 int = 0
类型 描述 取值范围
uint 无符号整型,由操作系统位数决定是uint32还是uint64
uint8 无符号8位整数 0~255
uint16 无符号16位整数 0~65535
uint32 无符号32位整数 0~4294967295
uint64 无符号64位整数 0~18446744073709551615
int 有符号整型,由操作系统位数决定是int32还是int64
int8 有符号8位整数 -128~127
int16 有符号16位整数 -32768~32767
int32 有符号32位整数 -2147483648~2147483647
int64 有符号64位整数 -9223372036854775808~9223372036854775807
进制表示
  • 在go语言中不能用字面量直接表示二进制数据

  • 描述八进制的数值,需要以0开头

1
var octal = 07
  • 描述十六进制的数值,需要以0x开头
1
var hexadecimal = 0xF

浮点型

  • 默认值为0.0
1
var 变量名 float64 = 0.0
类型 描述
float32 IEEE-754 32位浮点型数
float64 IEEE-754 64位浮点型数
complex64 32位实数和虚数
complex128 64位实数和虚数

其他数值

类型 描述
rune 类似int32
uintptr 用于存放指针,无符号整型

布尔型

  • 默认值为false
1
var 变量名 bool = true
1
var 变量名 bool = false

字符类型

1
var 变量名 byte = ''
类型 描述
byte uint8类型的别名

字符串类型

  • 字符串结尾由编译器自动追加\0作为字符串结尾标识符
1
var 变量名 string = ""

派生类型

指针类型

1
2
var 变量名 int = 0
p := &变量名

数组类型

1
变量名 := [数组长度]数据类型 {值, 值}

切片类型

  • 实际上是动态数组
1
变量名 := []数据类型 {值, 值}

映射类型

1
变量名 := map[键类型]值类型 {键: 值, 键: 值}

函数类型

1
func 函数名() {}
1
变量名 = func() {}

运算符

算术运算符

  • +(正号)、-(负号)
  • +(加号)、-(减号)、*/%
  • ++(自增)、--(自减)

自增运算符和自减运算符只能用于变量之后
自增运算符和自减运算符只能单独使用,不能用在表达式中

1
2
var a int
a++

关系运算符

  • ><>=<===!=

逻辑运算符

  • &&||!

赋值运算符

  • =+=-=*=/=%=
  • &=|=^=<<=>>=

按位运算符

  • &|^<<>>

内存地址运算符

  • &(取地址运算符)、*(解引用运算符)

分支语句

if语句

1
2
3
if 布尔表达式 {
布尔表达式成立时执行的代码
}
1
2
3
4
5
if 布尔表达式 {
布尔表达式成立时执行的代码
} else {
布尔表达式不成立时执行的代码
}
1
2
3
4
5
6
7
if 布尔表达式1 {
布尔表达式1成立时执行的代码
} else if 布尔表达式2 {
布尔表达式2成立时执行的代码
} else {
以上布尔表达式都不成立时执行的代码
}
1
2
3
4
5
if 布尔表达式1 {
if 布尔表达式2 {
布尔表达式12都成立时执行的代码
}
}

switch语句

  • Go语言的switch语句不具有穿透行为,在每个case语句中,无需使用break跳出seitch语句
1
2
3
4
5
6
7
8
switch 变量名 {
case1:
变量值为值1时执行的代码
case2:
变量值为值2时执行的代码
default:
变量值不为以上任何值时执行的代码
}
  • 如果需要强制穿透行为,需要在case语句结束后用fallthrough关键字
1
2
3
4
5
6
7
switch 变量 {
case1:
变量值为值1时执行的代码
fallthrough
case2:
变量值为值2时执行的代码
}

循环语句

for语句

1
2
3
for i := 起始值; 布尔表达式; i++ {
布尔表达式成立时反复执行的代码
}

遍历可遍历数据

  • 可遍历数据:字符串切片数组
1
2
3
4
for index, value := range 可遍历数据 {
fmt.Println("下标: ", index)
fmt.Println("数据: ", value)
}

逻辑上的while

  • Go语言中没有while循环,但是可以通过for语句逻辑上当作while循环使用
1
2
3
for 布尔表达式 {
布尔表达式成立时反复执行的代码
}

无限循环

1
2
3
for {
...
}
1
2
3
for true {
...
}
1
2
3
for ;; {
...
}

break关键字

  • 跳出循环
1
2
3
for {
break
}

continue关键字

  • 结束当前循环,开始下一次循环
1
2
3
for {
continue
}

跳转语句

  • 无条件跳转到指定位置

  • 定义一个跳转点

1
跳转点:
  • 立即跳转到指定跳转点
1
goto 跳转点

获取字符串长度

  • 一个英文字符的长度为1
  • 一个中文字符的长度为3

<str>:字符串

1
len(<str>)

完成

参考文献

哔哩哔哩——郭宏志-老郭
CSDN——一个大泥球
哔哩哔哩——喔咔咔耶耶
哔哩哔哩——Python路飞
哔哩哔哩——尚硅谷
腾讯云开发者社区——IT工作者
哔哩哔哩——喔咔咔耶耶