Go 语言基础学习文档
一、环境搭建
1.1 下载与安装
- **官方下载地址:**golang.org/dl/
- **官方镜像站(推荐):**golang.google.cn/dl/
- 安装方式:傻瓜式安装(按提示下一步即可完成)
1.2 安装验证
-
验证有没有安装成功
go version打印输出类似”go version go1.24.2 windows/amd64“,说明安装成功。
-
查看 Go 环境
go envGo1.11 版本之后无需手动配置环境变量,使用 go mod 管理项目,也不需要非得把项目放到 GOPATH 目录下,你可以在任意位置新建项目。
Go1.13 以后可以彻底不要 GOPATH 了。
1.3 开发工具
- 推荐使用 VSCode
- VSCode 安装 Go 语言插件(插件名称:Go)
二、基础语法
2.1 fmt 模块(格式化输出)
2.1.1 Print
用于基本打印输出,多参数打印无空格。
fmt.Print("a")
// a
fmt.Print("a", "b", "c")
// abc (PS:打印多个时,不会有空格)
2.1.2 Println
用于打印输出并支持格式化。
fmt.Println("a")
// a
// 换行
fmt.Println("a", "b", "c")
// a b c (PS:打印多个时,会有空格)
// 换行
2.1.3 Printf
用于格式化打印输出,支持占位符。
var a = 1
var b = 2
var c = 3
fmt.Printf("a=%v,b=%v,c=%v", a, b, c)
// a=1,b=2,c=3
fmt.Printf("a=%v,a的类型是%T", a, a)
// a=1,a的类型是int
2.2 变量与常量
2.2.1 变量
变量是程序运行过程中可以改变的量,Go 语言支持两种声明方式。
-
var 变量声明法
-
适用范围:可用于全局变量和局部变量。
-
基本用法
// 声明变量 var a string // 变量赋值 a = "a" // 声明变量并赋值 var a string = "a" // 声明变量并赋值,简写(类型推导,可省略) vat a = "a" // 一次声明多个变量(多个变量的类型都一样) var a, b, c, string a = "a" b = "b" c = "c" // 一次声明多个变量,(多个变量的类型可以不一样) var ( a string b int c bool ) // 一次声明多个变量并赋值 var ( a string = "a" b int = 1 c bool = true ) // 一次声明多个变量并赋值,简写(类型推导,可省略) var ( a = "a" b = 1 c = true )
-
-
短变量声明法
-
适用范围:仅用于函数内部的局部变量。
-
基本用法
// 声明变量并赋值 a := "a" // 一次声明多个变量并赋值 a, b, c := "a", 1, true
-
2.2.2 常量
常量是恒定不变的值,定义时必须赋值。
-
const 定义常量
// 声明常量并赋值 const a = "a" // 一次性声明多个常量并赋值 const ( a = "a" b = "b" ) -
常量省略值的特性
同时声明多个常量时,若省略值,则表示和上一行的值相同。
const ( a = "a" b c ) fmt.Printf("a = %v, b = %v, c = %v\n", a, b, c) // a = a, b = a, c = a
2.3 数据类型
Go 语言数据类型分为 基本数据类型 和 复合数据类型 两大类。
- 基本数据类型:整型、浮点型、布尔型、字符串
- 复合数据类型:数组、切片、结构体、函数、map、通道(channel)、接口等
2.3.1 整型 int
整型分为 有符号整型 和 无符号整型 两类,不同类型占用字节数不同。
-
声明示例
var num int = 1 fmt.Printf("num=%v,类型=%T\n", num, num) // num=1,类型=int -
整型分类
类型 有无符号 位数 取值范围 备注 int8 有符号 8 -128 到 127(-2^7到2^7-1) int16 有符号 16 -32768 到 32767(-2^15到2^15-1) int32 有符号 32 -2147483648 到 2147483647(-2^31到2^31-1) 别名:rune int64 有符号 64 -9223372036854775808 到 9223372036854775807(-2^63到2^63-1) uint8 无符号 8 0 到 255(0到2^8-1) 别名:byte uint16 无符号 16 0 到 65535(0到2^16-1) uint32 无符号 32 0 到 4294967295(0到2^32-1) uint64 无符号 64 0 到 18446744073709551615(0到2^64-1) int 有符号 系统相关 32位系统同int32,64位系统同int64 推荐优先使用 uint 无符号 系统相关 32位系统同uint32,64位系统同uint64 uintptr 无符号 系统相关 足够存储指针值的无符号整数 用于底层编程(如指针操作) -
整型类型转换
不同整型之间无法直接运算,需要强制类型转换,高位转低位时需注意数据溢出。
// 不同类型直接运算报错 var num1 int8 = 1 var num2 int16 = 1 fmt.Println(num1 + num2) // 报错 // 强制类型转换后运算 var num1 int8 = 1 var num2 int16 = 1 fmt.Println(int16(num1) + num2) // 输出:2 // 高位转低位的溢出问题 var num1 int16 = 130 fmt.Println(int8(num1)) // 输出:-126 -
数字字面量格式
符号 描述 %d 表示十进制输出 %b 表示二进制输出 %o 表示八进制输出 %x 表示十六进制输出 示例代码
num := 16 fmt.Printf("num=%v\n", num) // 输出:num=16 fmt.Printf("num=%d\n", num) // 输出:num=16 fmt.Printf("num=%b\n", num) // 输出:num=10000 fmt.Printf("num=%o\n", num) // 输出:num=20 fmt.Printf("num=%x\n", num) // 输出:num=10 -
获取变量占用字节数
使用
unsafe.Sizeof函数可以返回变量占用的字节数。num1 := int(1) num2 := int8(1) num3 := int16(1) num4 := int32(1) num5 := int64(1) fmt.Println(unsafe.Sizeof(num1)) // 输出:8 fmt.Println(unsafe.Sizeof(num2)) // 输出:1 fmt.Println(unsafe.Sizeof(num3)) // 输出:2 fmt.Println(unsafe.Sizeof(num4)) // 输出:4 fmt.Println(unsafe.Sizeof(num5)) // 输出:8
2.3.2 浮点型 float
Go 语言支持两种浮点型:float32 和 float64。
-
声明示例
// 类型推导,默认是float64 num := 3.1415926 fmt.Printf("num=%v,类型=%T\n", num, num) // 输出:num=3.1415926,类型=float64 // 显式声明float32 num1 := float32(3.1415926) fmt.Printf("num1=%v,类型=%T\n", num1, num1) // 输出:num1=3.1415925,类型=float32 // 显式声明float64 num2 := float64(3.1415926) fmt.Printf("num2=%v,类型=%T\n", num2, num2) // 输出:num2=3.1415926,类型=float64 -
浮点型范围
-
float32:最大范围约为 3.4e38 -
float64:最大范围约为 1.8e308示例代码
fmt.Println(math.MaxFloat32) // 输出:3.4028234663852886e+38 fmt.Println(math.MaxFloat64) // 输出:1.7976931348623157e+308
-
-
格式化输出
使用
%f占位符输出浮点型,可指定小数位数。num1 := 3.1415926 fmt.Printf("%v\n", num1) // 输出:3.1415926 fmt.Printf("%f\n", num1) // 输出:3.141593(默认保留6位,四舍五入) fmt.Printf("%.2f\n", num1) // 输出:3.14(保留2位) fmt.Printf("%.3f\n", num1) // 输出:3.142(保留3位) -
科学计数法
浮点型支持科学计数法表示。
num1 := 3.14e2 fmt.Printf("num1=%v,类型=%T\n", num1, num1) // 输出:num1=314,类型=float64 num2 := 3.14e-2 fmt.Printf("num2=%v,类型=%T\n", num2, num2) // 输出:num2=0.0314,类型=float64 -
精度丢失问题
二进制浮点数转换为十进制时可能存在精度丢失,可使用第三方包
github.com/shopspring/decimal解决。num := 1129.6 fmt.Println(num * 100) // 输出:112959.99999999999 num1 := 8.2 num2 := 3.8 fmt.Println(num1 - num2) // 输出:4.3999999999999995 -
浮点型与整型转换
-
整型转浮点型:直接强制转换,不会丢失数据
num1 := 3 num2 := float32(num1) fmt.Printf("num2=%v,类型=%T\n", num2, num2) // 输出:num2=3,类型=float32 num3 := float64(num1) fmt.Printf("num3=%v,类型=%T\n", num3, num3) // 输出:num3=3,类型=float64 -
浮点型转整型:强制转换会丢失小数部分
num1 := 3.14 num2 := int(num1) fmt.Printf("num2=%v,类型=%T\n", num2, num2) // 输出:num2=3,类型=int
-
2.3.2 布尔类型 bool
布尔型用 bool 表示,只有 true 和 false 两个值。
-
注意事项
- 布尔型变量默认值为
false - 不允许将整型强制转换为布尔型
- 布尔型无法参与数值运算,也无法与其他类型转换
- 布尔型变量默认值为
-
示例代码
var flag bool fmt.Printf("布尔类型的默认值=%v,类型=%T\n", flag, flag) // 输出:布尔类型的默认值=false,类型=bool num := 1 flag = bool(num) // 报错 if num { // 报错 fmt.Println("num为真") } str := "hello" flag = bool(str) // 报错 if str { // 报错 fmt.Println("str为真") }
2.3.4 字符串
字符串的值用双引号 "" 或反引号 `` 包裹。
-
注意事项
- 双引号用于表示单行字符串,支持转义符。
- 反引号用于表示多行字符串,原样输出内容,不解析转义符。
- 单引号
''用于表示字符,而非字符串。
-
字符串转义符
常见转义符如下表:
转义符 含义 \r 回车符 \n 换行符 \t 制表符 \' 单引号 \" 双引号 \\ 反斜杠 示例代码
str := "mumu: \"hello golang\"" fmt.Println(str) // 输出:mumu: "hello golang" -
多行字符串
Go 语言中要定义一个多行字符串时,就必须使用反引号。
multiLine := `这是第一行 这是第二行 这是带缩进的第三行 这是第四行` fmt.Println(multiLine) // 这是第一行 // 这是第二行 // 这是带缩进的第三行 // 这是第四行 -
字符串常用的方法
方法 功能 示例 len(str)返回字符串字节数 str := "mumu"; fmt.Println(len(str)) // 输出:4+拼接字符串 fmt.Println("hello" + " golang") // 输出:hello golangfmt.Sprintf格式化拼接字符串 str1:="hello";str2:="golang";str3:=fmt.Sprintf("%v %v",str1,str2) // str3为hello golangstrings.Split(str, sep)按分隔符分割字符串,返回切片 str:="hello golang";arr:=strings.Split(str," ");fmt.Println(arr) // 输出:[hello golang]strings.Join(arr, sep)将切片按分隔符合并为字符串 arr:=[]string{"hello","golang"};str:=strings.Join(arr,"-");fmt.Println(str) // 输出:hello-golangstrings.Contains(str1, str2)判断 str1 是否包含 str2 str1:="hello golang";str2:="ello";fmt.Println(strings.Contains(str1,str2)) // 输出:truestrings.HasPrefix(str1, str2)判断 str1 是否以 str2 开头 str1:="hello golang";str2:="hello";fmt.Println(strings.HasPrefix(str1,str2)) // 输出:truestrings.HasSuffix(str1, str2)判断 str1 是否以 str2 结尾 str1:="hello golang";str2:="golang";fmt.Println(strings.HasSuffix(str1,str2)) // 输出:truestrings.Index(str, substr)查找 substr 在 str 中首次出现的索引,不存在返回 -1 fmt.Println(strings.Index("hello golang","golang")) // 输出:6strings.LastIndex(str, substr)查找 substr 在 str 中最后出现的索引,不存在返回 -1 fmt.Println(strings.LastIndex("hello golang","an")) // 输出:9
2.3.5 byte & rune
byte 和 rune 是 Go 语言中用于表示字符的专属类型,底层都是整型的别名。
-
byte 与 rune 的区别
类型 底层类型 占用字节 适用场景 byte uint8 1 表示 ASCII 字符(0-127 范围) rune int32 4 表示 Unicode 字符(如中文、emoji 等) -
字符串遍历
-
for i循环遍历(按字节)Go 字符串底层是字节数组,
for i循环遍历的是每个字节的值。s := "Hello 世界" for i := 0; i < len(s); i++ { fmt.Printf("%x ", s[i]) // 输出:48 65 6c 6c 6f 20 e4 b8 96 e7 95 8c } -
for range遍历(按 rune)for range会自动将字符串按 Unicode 字符拆分,遍历的是rune类型的值。s := "Hello 世界" for _, r := range s { fmt.Printf("%c ", r) // 输出:H e l l o 世 界 }
-
-
字符串长度计算
-
len (str):返回字节数
对于包含多字节字符的字符串,字节数大于字符数。
str:= "go 你好" fmt.Println(len(str)) // 输出:9(go占2字节,空格占1,你好各占3,共2+1+3+3=9) -
len ([] rune (str)):返回字符数
将字符串转为
rune切片后,再计算长度即可得到字符数。str:= "go 你好" fmt.Println(len([]rune(str))) // 输出:5 -
utf8.RuneCountInString (str):返回字符数
使用
unicode/utf8包的函数直接获取字符数。str:= "go 你好" fmt.Println(utf8.RuneCountInString(str)) // 输出:5
-
持续更新中...