【笔记】Go语言学习笔记

前言

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

查看Go环境

1
go env

编译源码为可执行文件

<file>.go:Go语言源代码文件,如果省略,go会自动寻找当前目录下的main函数执行

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

输出到指定位置和指定文件名

<file_out>:输出的文件名及文件路径

1
go build -o <file_out> <file>.go

编译并运行一个Go源码

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

1
go run <file>.go

踩坑

  • 报错:package command-line-arguments is not a main package

解决问题

  • 将包名改为package main即可

初始化一个Go项目

新建一个主模块

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

func main() {
...
}

创建一个子模块

1
2
mkdir app
touch app/app.go
app/app.go
1
2
3
4
5
package app

func App() string {
return ""
}

注释

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

语句分隔符

  • 通过;和换行符作为语句分隔符
1
2
3
4
语句;语句

语句
语句

输出语句

带换行的输出语句

1
2
3
import "fmt"

fmt.Println("")

输出数据类型

1
fmt.Println(reflect(""))

不带换行的输出语句

1
2
3
import "fmt"

fmt.Print("")

格式化输出

1
2
3
import "fmt"

fmt.Printf("%d", 0)
格式说明符 数据类型 描述
%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
2
3
import "fmt"

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

格式化拼接字符串

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

输入语句

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

输入单个数据

1
2
3
4
5
6
7
8
package main

import "fmt"

func main() {
var 变量名 数据类型
fmt.Scan(&变量名)
}

输入多个数据

  • 通过空格分隔,获取多个输入的数据
  • 通过换行符也可以继续输入
1
2
3
4
5
6
7
8
9
package main

import "fmt"

func main() {
var 变量名1 数据类型
var 变量名2 数据类型
fmt.Scan(&变量名1, &变量名2)
}

强制换行结束

  • 通过空格分隔,获取多个输入的数据
  • 在输入换行符的时候,会立即结束输入的接收
1
2
3
4
5
6
7
8
9
package main

import "fmt"

func main() {
var 变量名1 数据类型
var 变量名2 数据类型
fmt.Scanln(&变量名1, &变量名2)
}

格式化输入

1
2
3
4
5
6
7
8
package main

import "fmt"

func main() {
var 变量名 数据类型
fmt.Scanf("%d", &变量名)
}

变量名命名规则

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

Go命名规范

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

变量

声明一个变量

  • 通过var关键字定义一个变量
1
var 变量名 数据类型

声明多个变量

1
2
3
4
var (
变量名 数据类型
变量名 数据类型
)

为变量赋值

  • Go中声明变量后必须使用,否则会报错
1
变量名 = 变量值

变量的初始化

  • 在声明变量时直接赋值
1
var 变量名 数据类型 = 变量值

类型推断

  • 在初始化变量时,可以省略数据类型的定义,通过变量值自动推断数据类型
1
var 变量名 = 变量值

短变量声明

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

批量初始化

1
2
var 变量名1, 变量名2, 变量名3 = 变量值1, 变量值2, 变量值3
变量名1, 变量名2, 变量名3 := 变量值1, 变量值2, 变量值3

交换变量的值

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

匿名变量

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

常量

定义一个常量

  • 常量在定义时必须赋值
  • 常量的数据类型只能是string、int、float、bool类型
1
const 常量名 数据类型 = 常量值

字面常量

  • 没有定义常量名而直接使用的常量
1
fmt.Println(1)

类型推导

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
常量名 = iota
常量名 = iota
)

省略

  • 如果定义常量时省略了赋值,将会自动按照上一次赋值
1
2
3
4
5
const (
常量名 = iota
常量名
常量名
)

相同常量值

  • 在同一行定义的常量,iota的常量值相同
1
2
3
4
5
const (
常量名 = iota
常量名, 常量名 = iota, iota
常量名, 常量名
)

跳过

  • 如果想跳过当前值,可以使用匿名接收,以达到跳过常量值的效果
1
2
3
4
5
const (
常量名 = iota
_ = iota
常量名 = iota
)

中间插队

  • 如果在使用iota作为常量值的期间有其他常量值被赋值,此时也会达到跳过常量值的效果
1
2
3
4
5
const (
常量名 = iota
常量名 = 常量值
常量名 = iota
)

重置

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

数据类型

数值型

整型

  • 默认值为0
  • 默认直接指定int,则跟随操作系统
    • 32位操作系统采用32个位
    • 64位操作系统采用64个位
1
var 变量名 int = 0
类型 描述 取值范围
uint8 无符号8位整数 0~255
uint16 无符号16位整数 0~65535
uint32 无符号32位整数 0~4294967295
uint64 无符号64位整数 0~18446744073709551615
int8 有符号8位整数 -128~127
int16 有符号16位整数 -32768~32767
int32 有符号32位整数 -2147483648~2147483647
int64 有符号64位整数 -9223372036854775808~9223372036854775807
二进制数
  • 在go语言中不能直接表示二进制数据
八进制数
  • 0开头
1
num := 07
十六进制
  • 0x开头
1
num := 0xF

浮点型

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

其他数值

类型 描述
rune 类似int32
uint 32位或64位
int uint一样大小
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
func 函数名() {}

分支语句

if语句

1
2
3
if 逻辑表达式 {
...
}
1
2
3
4
5
if 逻辑表达式 {
...
} else {
...
}
1
2
3
4
5
if 逻辑表达式 {
...
} else if 逻辑表达式 {
...
}
1
2
3
4
5
if 逻辑表达式 {
if 逻辑表达式 {
...
}
}

switch语句

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

循环语句

for语句

1
2
3
for i := 0; i < 1; i++ {
...
}
1
2
3
4
5
for i := 0; i < 1; i++ {
for j := 0; j < 1; j++ {
...
}
}

遍历可遍历数据

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

逻辑上的while

  • Go语言中没有while循环,但是可以通过for语句逻辑上当作while循环使用
1
2
3
4
5
6
7
var i int = 0
for i < 100 {

...

i++
}

无限循环

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

continue关键字

  • 结束当前循环,继续下次循环

break关键字

  • 结束所有循环

跳转语句

  • 无条件跳转到指定位置

定义一个跳转点

label:跳转点名称

1
label:

立即跳转到指定跳转点

1
goto label

获取字符串长度

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

<str>:字符串

1
len(<str>)

运算符

算术运算符

  • +-*/(整除)、%(取余)、++(自增)、--(自减)

整除运算符和取余运算符除数都不能为0
取余运算符除数不能为浮点数
自增运算符和自减运算符只能用于变量之后
自增运算符和自减运算符只能单独使用,不能用在表达式中

赋值运算符

  • =+=-=*=/=%=

  • Go语言也支持自增和自减运算,但是不允许将自增结果或自减结果赋值给其他变量

关系运算符

  • 关系运算符得到的结果都是布尔值
  • ==><>=<=!=

逻辑运算符

  • 逻辑运算符只能对布尔类型表达式或布尔类型值使用
  • &&||!

特殊运算符

  • &(取址符)、*(取值符)

按位运算符

  • <<>>&|^

完成

参考文献

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