1.If语句
Go语言 中的 if语句 格式与 c语言 基本一样,只是 go 的 if语句 可以带简短变量声明
if num := 10; num > 5 { fmt.Println("num is greater than 5") // 输出: num is greater than 5 } // fmt.Println(num) // ❌ 编译错误,num 仅在 if 语句内有效
2.for语句
在 Go语言 中,for 是唯一的循环关键字,没有 while 或 do-while 语句。但 for 语句可以模拟 while 循环等其他循环形式,语法灵活
break 、 continue 和 goto 关键字在 for 循环中的用法与 c语言 相同
// 基本形式 for 初始化语句; 条件表达式; 迭代语句 { // 循环体 }
Go 语言的 for-range 用于遍历可迭代的数据结构(切片、数组、字符串、映射和通道),返回索引和值
// 基本形式 nums := []int{10, 20, 30, 40} for index, value := range nums { fmt.Printf("Index: %d, Value: %d\n", index, value) }
3.切片
在 Go语言 中,切片(Slice)是动态大小的数组,是 Go语言 中最常用的数据结构之一。与数组不同,切片的长度可以动态变化,并且切片本质上是一个指向底层数组的引用。
切片的定义
var nums []int // 定义一个 int 类型的切片 fmt.Println(nums) // 输出: [] // 注意如果定义时指定了长度,则是定义了一个 int 类型数组 nums var arr [5]int // 定义一个长度为 5 的整数数组 fmt.Println(arr) // 输出: [0 0 0 0 0]
ps:切片的零值是nil,即 var s []int 定义 s 后,s == nil 为 true
直接赋值切片
slice := []int{1, 2, 3, 4, 5} fmt.Println(slice) // 输出: [1 2 3 4 5]
ps:[]int{} 直接创建一个切片,不需要 var 或 make
使用 make() 创建切片
// 基本语法 slice := make([]Type, length, capacity) // 如果不指定 capacity ,则 capacity 默认等于 length slice := make([]int, 5) // 创建一个长度为 5 的切片 fmt.Println(slice) // 输出: [0 0 0 0 0]
切片基本操作
// 1.遍历切片 // 1.1 使用 for 语句 slice := []int{10, 20, 30} for i := 0; i < len(slice); i++ { fmt.Println(slice[i]) } // 1.2 使用 for-range 语句 for index, value := range slice { fmt.Printf("Index: %d, Value: %d\n", index, value) } // 2.切片截取 slice := []int{10, 20, 30, 40, 50} newSlice := slice[1:4] // 截取索引 1~3(不包括 4) fmt.Println(newSlice) // 输出: [20 30 40]
切片的动态扩容
slice := []int{1, 2, 3} slice = append(slice, 4, 5, 6) fmt.Println(slice) // 输出: [1 2 3 4 5 6] // 将一个切片的值作为另一个切片的扩展 moreNumbers := []int{7, 8, 9} slice = append(slice, moreNumbers...) // 使用 `...` 将另一个切片展开 fmt.Println(slice) // 输出: [1 2 3 4 5 6 7 8 9]
切片的容量增长
当 append() 使切片容量超过当前 cap,Go语言 会创建新的底层数组,并将数据复制过去。
slice := make([]int, 2, 4) // 长度 2,容量 4 fmt.Println(len(slice), cap(slice)) // 输出: 2 4 slice = append(slice, 100) slice = append(slice, 200) // 此时容量刚好满 slice = append(slice, 300) // 触发扩容(一般是 2 倍增长) fmt.Println(len(slice), cap(slice)) // 输出: 5 8
copy() 复制切片
src := []int{1, 2, 3, 4, 5} dst := make([]int, len(src)) // 目标切片必须有足够的空间 copy(dst, src) fmt.Println(dst) // 输出: [1 2 3 4 5]
切片的底层数组共享
arr := [5]int{1, 2, 3, 4, 5} slice1 := arr[1:4] // [2, 3, 4] slice2 := arr[2:5] // [3, 4, 5] fmt.Println(slice1, slice2) // 输出: [2 3 4] [3 4 5] slice1[1] = 100 // 修改 slice1 fmt.Println(arr) // 底层数组变了: [1 2 100 4 5] fmt.Println(slice2) // slice2 也受影响: [100 4 5]
4.字符串
字符串的定义
// 1.使用双引号 // 特点:支持转义字符 s := "Hello, Go!" fmt.Println(s) // 输出: Hello, Go! // 2.使用反引号 // 特点:支持多行内容,不解析转义字符 s : `Hello, Go! This is a raw string.` fmt.Println(s)
ps:Go语言 中的 string 是不可变的,不能直接修改其中的字符。如果想修改字符串,可以转换为 []byte
或 []rune
b := []byte(s) // 转换为 byte 切片 b[0] = 'H' s = string(b) // 重新转换回 string fmt.Println(s) // 输出: Hello
获取字符串长度
s := "Hello" fmt.Println(len(s)) // 输出: 5 s := "你好" fmt.Println(len(s)) // 输出: 6 (因为 UTF-8 编码中 "你" 和 "好" 各占 3 个字节)
要获取实际字符数,需要用 rune 处理:
s := "你好" fmt.Println(len([]rune(s))) // 输出: 2
遍历字符串
// 按字节遍历 s := "你好" for i := 0; i < len(s); i++ { fmt.Printf("Index %d: %x\n", i, s[i]) } // 按字符遍历 s := "你好" for i, r := range s { fmt.Printf("Index %d: %c\n", i, r) }
字符串的拼接
// 使用 “+” 拼接 s1 := "Hello" s2 := "World" s := s1 + ", " + s2 + "!" fmt.Println(s) // 输出: Hello, World! // 注意 “+” 只能用于字符串拼接。如果需要拼接整数,使用 fmt.sprintf age := 25 s := fmt.Sprintf("My age is %d", age) fmt.Println(s) // 输出: My age is 25 // 使用 strings.Join() 高效拼接,对于大量字符串拼接,strings.Join() 比 “+” 更高效 import "strings" s := strings.Join([]string{"Go", "is", "awesome"}, " ") fmt.Println(s) // 输出: Go is awesome
字符串切片
s := "Hello, World!" sub := s[7:12] fmt.Println(sub) // 输出: World // 注意不能超出 len(s), 否则会 panic
字符串查找
import "strings" // 使用strings.Containers() fmt.Println(strings.Contains("golang", "go")) // true fmt.Println(strings.Contains("golang", "java")) // false // 使用strings.Index() fmt.Println(strings.Index("golang", "go")) // 0 fmt.Println(strings.Index("golang", "g")) // 0 fmt.Println(strings.Index("golang", "a")) // 3 fmt.Println(strings.Index("golang", "x")) // -1 (未找到)