Go 语言基础学习文档

Go 语言基础学习文档

一、环境搭建

1.1 下载与安装

  • 官方下载地址: golang.org/dl/
  • 官方镜像站(推荐): golang.google.cn/dl/
  • 安装方式:傻瓜式安装(按提示下一步即可完成)

1.2 安装验证

  1. 验证有没有安装成功
go version

#Go打印输出类似”go version go1.24.2 windows/amd64“,说明安装成功。

  1. 查看 Go 环境
go env

Go1.11 版本之后无需手动配置环境变量,使用 go mod 管理项目,也不需要非得把项目放到 GOPATH 目录下,你可以在任意位置新建项目。

Go1.13 后来可以彻底不要 GOPATH 了。

1.3 开发工具

  1. 推荐使用 VSCode
  2. 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 语言支持两种声明方式。

  1. var 变量声明法
  2. 适用范围:可用于全局变量和局部变量。
  3. 基本用法
// 声明变量
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 )
  1. 短变量声明法
  2. 适用范围:仅用于函数内部的局部变量。
  3. 基本用法
// 声明变量并赋值
a := "a"

// 一次声明多个变量并赋值 a, b, c := "a", 1, true

2.2.2 常量

常量是恒定不变的值,定义时必须赋值。

  1. const 定义常量
// 声明常量并赋值
const a = "a"

// 一次性声明多个常量并赋值 const ( a = "a" b = "b" )
  1. 常量省略值的特性

同时声明多个常量时,若省略值,则表明和上一行的值一样。

const (
    a = "a"
    b
    c
)
fmt.Printf("a = %v, b = %v, c = %v
", a, b, c)
// a = a, b = a, c = a

2.3 数据类型

Go 语言数据类型分为 基本数据类型复合数据类型 两大类。

  • 基本数据类型:整型、浮点型、布尔型、字符串
  • 复合数据类型:数组、切片、结构体、函数、map、通道(channel)、接口等

2.3.1 整型 int

整型分为 有符号整型无符号整型 两类,不同类型占用字节数不同。

  1. 声明示例
var num int = 1
fmt.Printf("num=%v,类型=%T
", num, num)
// num=1,类型=int
  1. 整型分类

| 类型 | 有无符号 | 位数 | 取值范围 | 备注 | | —

| 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 | 无符号 | 系统相关 | 足够存储指针值的无符号整数 | 用于底层编程(如指针操作) |

  1. 整型类型转换

不同整型之间无法直接运算,需要强制类型转换,高位转低位时需注意数据溢出。

// 不同类型直接运算报错
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
  1. 数字字面量格式

| 符号 | 描述 | | —

| %d | 表明十进制输出 | | %b | 表明二进制输出 | | %o | 表明八进制输出 | | %x | 表明十六进制输出 |

示例代码

num := 16
fmt.Printf("num=%v
", num)  // 输出:num=16
fmt.Printf("num=%d
", num)  // 输出:num=16
fmt.Printf("num=%b
", num)  // 输出:num=10000
fmt.Printf("num=%o
", num)  // 输出:num=20
fmt.Printf("num=%x
", num)  // 输出:num=10
  1. 获取变量占用字节数

使用 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 。

  1. 声明示例
// 类型推导,默认是float64
num := 3.1415926
fmt.Printf("num=%v,类型=%T
", num, num) // 输出:num=3.1415926,类型=float64

// 显式声明 float32 num1 := float32(3.1415926) fmt.Printf("num1=%v,类型=%T
", num1, num1) // 输出:num1=3.1415925,类型=float32

// 显式声明 float64 num2 := float64(3.1415926) fmt.Printf("num2=%v,类型=%T
", num2, num2) // 输出:num2=3.1415926,类型=float64
  1. 浮点型范围
  2. float32 :最大范围约为 3.4e38
  3. float64 :最大范围约为 1.8e308

示例代码

fmt.Println(math.MaxFloat32) // 输出:3.4028234663852886e+38
fmt.Println(math.MaxFloat64) // 输出:1.7976931348623157e+308
  1. 格式化输出

使用 %f 占位符输出浮点型,可指定小数位数。

num1 := 3.1415926
fmt.Printf("%v
", num1)    // 输出:3.1415926
fmt.Printf("%f
", num1)    // 输出:3.141593(默认保留6位,四舍五入)
fmt.Printf("%.2f
", num1)  // 输出:3.14(保留2位)
fmt.Printf("%.3f
", num1)  // 输出:3.142(保留3位)
  1. 科学计数法

浮点型支持科学计数法表明。

num1 := 3.14e2
fmt.Printf("num1=%v,类型=%T
", num1, num1) // 输出:num1=314,类型=float64

num2 := 3.14e-2 fmt.Printf("num2=%v,类型=%T
", num2, num2) // 输出:num2=0.0314,类型=float64
  1. 精度丢失问题

二进制浮点数转换为十进制时可能存在精度丢失,可使用第三方包
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
  1. 浮点型与整型转换
  2. 整型转浮点型:直接强制转换,不会丢失数据
num1 := 3
num2 := float32(num1)
fmt.Printf("num2=%v,类型=%T
", num2, num2) // 输出:num2=3,类型=float32

num3 := float64(num1) fmt.Printf("num3=%v,类型=%T
", num3, num3) // 输出:num3=3,类型=float64
  • 浮点型转整型:强制转换会丢失小数部分
num1 := 3.14
num2 := int(num1)
fmt.Printf("num2=%v,类型=%T
", num2, num2) // 输出:num2=3,类型=int

2.3.2 布尔类型 bool

布尔型用 bool 表明,只有 true 和 false 两个值。

  1. 注意事项
  2. 布尔型变量默认值为 false
  3. 不允许将整型强制转换为布尔型
  4. 布尔型无法参与数值运算,也无法与其他类型转换
  5. 示例代码
var flag bool
fmt.Printf("布尔类型的默认值=%v,类型=%T
", 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 字符串

字符串的值用双引号 “” 或反引号 ` “` 包裹。

  1. 注意事项
  2. 双引号用于表明单行字符串,支持转义符。
  3. 反引号用于表明多行字符串,原样输出内容,不解析转义符。
  4. 单引号 '' 用于表明字符,而非字符串。
  5. 字符串转义符

常见转义符如下表:

| 转义符 | 含义 | | —

|
| 回车符 | |
| 换行符 | | | 制表符 | | ' | 单引号 | | ” | 双引号 | | | 反斜杠 |

示例代码

str := "mumu: "hello golang""
fmt.Println(str) // 输出:mumu: "hello golang"
  1. 多行字符串

Go 语言中要定义一个多行字符串时,就必须使用反引号。

multiLine := `这是第一行
这是第二行
    这是带缩进的第三行
这是第四行`
    fmt.Println(multiLine)
// 这是第一行
// 这是第二行
//         这是带缩进的第三行
// 这是第四行
  1. 字符串常用的方法

| 方法 | 功能 | 示例 | | —

| len(str) | 返回字符串字节数 | str := “mumu”; fmt.Println(len(str)) // 输出:4 | | +

| fmt.Sprintf | 格式化拼接字符串 | str1:=”hello”;str2:=”golang”;str3:=fmt.Sprintf(“%v %v”,str1,str2) // str3为 hello golang | | strings.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-golang | | strings.Contains(str1, str2) | 判断 str1 是否包含 str2 | str1:=”hello golang”;str2:=”ello”;fmt.Println(strings.Contains(str1,str2)) // 输出:true | | strings.HasPrefix(str1, str2) | 判断 str1 是否以 str2 开头 | str1:=”hello golang”;str2:=”hello”;fmt.Println(strings.HasPrefix(str1,str2)) // 输出:true | | strings.HasSuffix(str1, str2) | 判断 str1 是否以 str2 结尾 | str1:=”hello golang”;str2:=”golang”;fmt.Println(strings.HasSuffix(str1,str2)) // 输出:true | | strings.Index(str, substr) | 查找 substr 在 str 中首次出现的索引,不存在返回 -1 | fmt.Println(strings.Index(“hello golang”,”golang”)) // 输出:6 | | strings.LastIndex(str, substr) | 查找 substr 在 str 中最后出现的索引,不存在返回 -1 | fmt.Println(strings.LastIndex(“hello golang”,”an”)) // 输出:9 |

2.3.5 byte & rune

byte 和 rune 是 Go 语言中用于表明字符的专属类型,底层都是整型的别名。

  1. byte 与 rune 的区别

| 类型 | 底层类型 | 占用字节 | 适用场景 | | —

| byte | uint8 | 1 | 表明 ASCII 字符(0-127 范围) | | rune | int32 | 4 | 表明 Unicode 字符(如中文、emoji 等) |

  1. 字符串遍历
  2. 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  世 界
}
  1. 字符串长度计算
  2. 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
  1. 修改字符串

修改字符串,需要将其转换成 []rune 或者 []byte ,完成后再转换成 string 。无论哪种转换,都会重新分配内存,并复制字节数组。

s := "abc"
byteStr := []byte(s)
byteStr[0] = 'A'
fmt.Println(string(byteStr)) // Abc

s2 := "你好 goland" runeStr := []rune(s2) runeStr[0] = '我' fmt.Println(string(runeStr)) // 我好 goland

2.3.6 基本数据类型之间的转换

  1. 数值类型之间的转换

数值类型包括:整形、浮点型

// 整形与整形之间的转换(错误)
var a int8 = 1
var b int16 = 2
var c = a +

fmt.Printf("%v(%T)", c, c)

// 整形与整形之间的转换(正确) var a int8 = 1 var b int16 = 2 var c = int16(a) +

fmt.Printf("%v(%T)", c, c) // 3(int16)

// 浮点型与浮点型之间的转换(错误) var a float32 = 1 var b float64 = 2 var c = a +

fmt.Printf("%v(%T)", c, c)

// 浮点型与浮点型之间的转换(正确) var a float32 = 1 var b float64 = 2 var c = float64(a) +

fmt.Printf("%v(%T)", c, c) // 3(float64)

// 整形与浮点型之间的转换(错误) var a int32 = 1 var b float32 = 2 var c = a +

fmt.Printf("%v(%T)", c, c)

// 整形与浮点型之间的转换(正确) var a int32 = 1 var b float32 = 2 var c = float32(a) +

fmt.Printf("%v(%T)", c, c) // 3(float32)

注意:转换的时候,提议从低位转换成高位,高位转换成低位不成功就会溢出。

  1. 其他类型转换成 String 类型

持续更新中…

© 版权声明

相关文章

暂无评论

none
暂无评论...