【笔记】Go语言学习笔记

前言

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

查看Go环境

1
go env

编译源码为可执行文件

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

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

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

1
go build -o <filename>.go

编译并运行一个Go源码

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

1
go run <filename>.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("")

格式化输出

占位符

%b:二进制整型数据占位符
%o:八进制整型数据占位符
%d:十进制整型数据占位符

%3d:整型数据占位符,如果不满足3位,用空格补齐空位,从前面补齐
%-3d:整型数据占位符,如果不满足3位,用空格补齐空位,从后面补齐
%03d:整型数据占位符,如果不满足3位,用0补齐空位,从前面补齐
%-03d:整型数据占位符,如果不满足3位,用0补齐空位,从后面补齐

%x:十六进制整型数据占位符,字母小写
%X:十六进制整型数据占位符,字母大写
%p:十六进制指针类型占位符

%f:浮点数据占位符,默认保留6位小数,自动四舍五入
%.3f:浮点数据占位符,保留小数点后3位小数,自动四舍五入

%t:布尔类型占位符
%c:字符类型占位符
%s:字符串类型占位符
%%%转义字符

1
2
3
import "fmt"

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

输出数据的类型

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

数据类型

布尔型

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

数值型

整型

  • 默认值为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 用于存放指针,无符号整型

字符类型

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语句

  • 默认只执行当前分之的代码
  • 如果某一分之包含fallthrough语句,则自动执行下一分之代码
  • 不符合所有条件时,执行default的代码
1
2
3
4
5
6
7
8
9
switch 变量 {
case 值:
...
fallthrough
case 值:
...
default:
...
}

循环语句

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语言也支持自增和自减运算,但是不允许将自增结果或自减结果赋值给其他变量

关系运算符

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

逻辑运算符

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

特殊运算符

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

按位运算

  • <<>>&|^

强制类型转换

<value>:需要被转换的数据

转换为浮点型

1
float64(<value>)

完成

参考文献

哔哩哔哩——郭宏志-老郭
CSDN——一个大泥球
哔哩哔哩——喔咔咔耶耶
哔哩哔哩——Python路飞
哔哩哔哩——尚硅谷