深度剖析Golang中的数组,字符串和切片
作者:金刀大菜牙 时间:2024-02-17 08:53:13
1. 数组
数组是 Golang 中的一种基本数据类型,用于存储固定数量的同类型元素。在 Golang 中,数组的长度是固定的,并且必须在定义数组时指定。
1.1 定义数组
在 Golang 中,可以使用以下语法声明数组:
var 数组名称 [数组长度]数据类型
例如,要声明一个由 5 个整数组成的数组,可以使用以下代码:
var arr [5]int
上面的代码定义了一个名为 arr 的数组,包含 5 个整数元素。可以使用以下方式初始化数组中的元素:
arr := [5]int{1, 2, 3, 4, 5}
上面的代码定义了一个名为arr的数组,包含 5 个整数元素。元素的值分别为 1、2、3、4 和 5。
我们也可以在声明期间为数组进行初始化,方法是为其元素提供值。例如,要初始化一个由 3 个字符串组成的数组,可以使用以下代码:
var names [3]string = [3]string{"Alice", "Bob", "Charlie"}
1.2 访问数组
可以使用索引运算符([])来访问数组中的元素。数组中的第一个元素的索引为 0,最后一个元素的索引为长度 -1。例如,可以使用以下方式访问数组中的元素:
arr := [5]int{1, 2, 3, 4, 5}
fmt.Println(arr[0]) // 输出1
fmt.Println(arr[1]) // 输出2
fmt.Println(arr[2]) // 输出3
上面的代码输出了数组中的前三个元素。
1.3 修改数组
可以使用以下方式修改数组中的元素:
arr := [5]int{1, 2, 3, 4, 5}
arr[0] = 10
fmt.Println(arr) // 输出[10 2 3 4 5]
上面的代码将数组中的第一个元素修改为 10,并输出了修改后的数组。
1.4 数组长度
在 Golang 中,可以使用 len 函数获取数组的长度。例如,以下代码获取数组 arr 的长度:
arr := [5]int{1, 2, 3, 4, 5}
length := len(arr)
fmt.Println(length) // 输出5
1.5 遍历数组
可以使用 for 循环遍历数组中的元素。例如,以下代码遍历了数组 arr 中的元素:
arr := [5]int{1, 2, 3, 4, 5}
for i := 0; i lt; len(arr); i++ {
fmt.Println(arr[i])
}
上面的代码输出了数组中的所有元素。
1.6 多维数组
Golang 还支持多维数组。以下是一个定义和初始化二维数组的示例:
var arr [3][3]int
arr = [3][3]int{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
}
fmt.Println(arr)
上面的代码定义了一个 3x3 的二维数组,并初始化了数组中的所有元素。可以使用以下方式访问数组中的元素:
fmt.Println(arr[0][0]) // 输出1
fmt.Println(arr[0][1]) // 输出2
fmt.Println(arr[1][0]) // 输出4
fmt.Println(arr[2][2]) // 输出9
当我们知道要存储的元素数量并且在运行时不需要更改数组的大小时,数组非常有用。但是,在需要更灵活的数据类型以动态更改其大小时,我们就需要使用切片。
2. 切片
切片是 Golang 中一种灵活的数据结构,用于处理可变长度的元素集合。切片是由底层数组、长度和容量组成的。切片的长度表示切片中元素的数量,容量表示切片所引用的底层数组中元素的数量。
2.1 定义切片
切片是建立在数组之上的动态数据结构。可以使用以下语法声明切片:
var 切片名称 []数据类型
例如,要声明一个整数切片,可以使用以下代码:
var slice []int
上面的代码定义了一个名为 slice 的切片,不包含任何元素。
可以使用以下方式初始化切片中的元素:
slice := []int{1, 2, 3, 4, 5}
上面的代码定义了一个名为 slice 的切片,包含 5 个整数元素。元素的值分别为 1、2、3、4 和 5。
2.2 访问切片元素
可以使用以下方式访问切片中的元素:
slice := []int{1, 2, 3, 4, 5}
fmt.Println(slice[0]) // 输出1
fmt.Println(slice[1]) // 输出2
fmt.Println(slice[2]) // 输出3
上面的代码输出了切片中的前三个元素。
2.3 修改切片元素
可以使用以下方式修改切片中的元素:
slice := []int{1, 2, 3, 4, 5}
slice[0] = 10
fmt.Println(slice) // 输出[10 2 3 4 5]
上面的代码将切片中的第一个元素修改为 10,并输出了修改后的切片。
2.4 切片长度和容量
可以使用 len 函数获取切片的长度,使用 cap 函数获取切片的容量。例如,以下代码获取切片 slice 的长度和容量:
slice := []int{1, 2, 3, 4, 5}
length := len(slice)
capacity := cap(slice)
fmt.Println(length) // 输出5
fmt.Println(capacity) // 输出5
注意,这里的容量等于长度,因为我们没有指定底层数组的长度。
2.5 向切片中添加元素
可以使用 append 函数向切片中添加元素。例如,以下代码向切片 slice 中添加一个元素 6:
slice := []int{1, 2, 3, 4, 5}
slice = append(slice, 6)
fmt.Println(slice) // 输出[1 2 3 4 5 6]
上面的代码将 6 添加到 slice 的末尾。
我们还可以一次性向切片中添加多个元素。例如,要向 “slice” 切片中添加整数 7、8 和 9,可以使用以下代码:
slice = append(slice, 7, 8, 9)
2.6 切片的切片
由于切片是动态的,因此可以轻松地将其传递给函数,并且不需要指定其大小。这使切片更加强大的一个重要特性是切片表达式。切片表达式是一个从切片中选择子序列的方法,其语法如下:
切片名称[开始索引:结束索引]
这将返回一个包含从开始索引到结束索引之间的元素的新切片。例如,要从 “numbers” 切片中选择索引为 1 到索引为 3 的元素,可以使用以下代码:
var subSlice = numbers[1:4]
注意,切片表达式中的开始索引包含在结果中,但结束索引不包含在结果中。在上面的例子中,结果将包含 “numbers” 切片中的第二、第三和第四个元素。
切片表达式还具有可选参数,它指定切片的最大容量。如果切片表达式为:
切片名称[开始索引:结束索引:最大容量]
则结果切片的容量将为最大容量-开始索引。这使得可以创建“截断”的切片,该切片不包含在开始索引和结束索引之间的任何元素,但可以容纳其他元素。
2.7 切片排序
Golang 中的 sort 包提供了多种排序算法,可以用于对切片进行排序。以下是一个对切片进行排序的示例:
slice := []int{3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5}
sort.Ints(slice)
fmt.Println(slice) // 输出[1 1 2 3 3 4 5 5 5 6 9]
上面的代码使用 Ints 函数对整数切片进行排序,并输出排序后的结果。
3. 字符串
字符串是不可变的字节序列。在 Golang 中,字符串是用双引号括起来的字符序列。例如,以下是一个字符串变量的声明:
var str string = "hello world"
与数组和切片不同,字符串不是一个内置类型。实际上,字符串是由字节数组表示的切片。由于字符串是不可变的,因此必须使用切片来操作它们。
3.1 访问字符串中的字符
要访问字符串中的字符,可以使用索引运算符。例如,以下代码将输出字符串 “hello world” 的第一个字符:
fmt.Println(str[0])
字符串中的每个字符都由一个字节表示。因此,访问字符串中的字符将返回该字节的ASCII码值。
3.2 字符串切片
我们可以使用切片表达式来创建新的字符串切片。例如,以下代码将创建一个新的字符串切片,其中包含字符串 “hello world” 的前 5 个字符:
var subStr = str[:5]
请注意,与切片一样,开始索引是包含在结果中的,但结束索引不包含在结果中。
3.3 字符串操作
Golang 提供了一些内置的字符串函数,使字符串操作更加方便。以下是其中一些常用的函数:
len():返回字符串的长度
strings.Contains():检查字符串中是否包含指定的子字符串
strings.Replace():将字符串中的指定子字符串替换为另一个字符串
strings.Split():将字符串拆分为子字符串的切片
strings.ToUpper() 和 strings.ToLower():将字符串中的字符转换为大写或小写
例如,以下代码使用 “strings.Contains” 函数检查字符串 “hello world” 是否包含子字符串 “world”:
var contains = strings.Contains(str, "world")
fmt.Println(contains) // 输出 true
3.4 关于字符串的常见问题
在 Golang 中,处理字符串时可能会遇到一些常见问题。以下是一些常见问题和解决方法:
3.4.1 如何将字符串转换为整数?
在 Golang 中,可以使用 strconv 包中的 Atoi 函数将字符串转换为整数。例如,以下代码将字符串 "123" 转换为整数 123:
import "strconv"
str := "123"
num, err := strconv.Atoi(str)
if err != nil {
fmt.Println("转换错误")
} else {
fmt.Println(num)
}
如果字符串不能转换为整数,则 Atoi 函数将返回一个错误。
3.4.2 如何将整数转换为字符串?
可以使用 strconv 包中的 Itoa 函数将整数转换为字符串。例如,以下代码将整数 123 转换为字符串 "123":
import "strconv"
num := 123
str := strconv.Itoa(num)
fmt.Println(str)
3.4.3 如何检查字符串是否为空?
可以使用 len 函数检查字符串是否为空。例如,以下代码检查字符串是否为空:
str := ""
if len(str) == 0 {
fmt.Println("字符串为空")
}
3.4.4 如何检查字符串是否包含另一个字符串?
可以使用 strings 包中的 Contains 函数检查一个字符串是否包含另一个字符串。例如,以下代码检查字符串 "hello world" 是否包含字符串 "world":
import "strings"
str := "hello world"
if strings.Contains(str, "world") {
fmt.Println("包含字符串world")
}
3.4.5 如何比较两个字符串?
可以使用 “==” 运算符比较两个字符串是否相等。例如,以下代码比较字符串 "hello" 和字符串 "hello":
str1 := "hello"
str2 := "hello"
if str1 == str2 {
fmt.Println("字符串相等")
}
3.4.6 如何将字符串拆分为子字符串?
可以使用 strings 包中的 Split 函数将字符串拆分为子字符串。例如,以下代码将字符串 "hello,world" 拆分为 "hello" 和 "world":
import "strings"
str := "hello,world"
arr := strings.Split(str, ",")
fmt.Println(arr)
3.4.7 如何将字符串转换为字节数组?
可以将字符串强制转换为 []byte 类型,这将返回一个包含字符串的字节数组。例如,以下代码将字符串 "hello" 转换为字节数组:
str := "hello"
bytes := []byte(str)
fmt.Println(bytes)
3.4.8 如何将字节数组转换为字符串?
可以使用 string 函数将字节数组转换为字符串。例如,以下代码将字节数组 []byte{104, 101, 108, 108, 111} 转换为字符串 "hello":
bytes := []byte{104, 101, 108, 108, 111}
str := string(bytes)
fmt.Println(str)
4. 总结
数组、字符串和切片是 Golang 中重要的数据结构。数组是一组固定大小的数据元素的集合,可以直接访问和修改数组中的元素。字符串是一个不可变的字节序列,可以通过下标访问字符串中的字节。切片是一个动态数组,可以根据需要动态增加或缩小大小。切片提供了方便的操作函数和语法,例如向切片中添加元素、获取切片的长度和容量、对切片进行排序等。
在 Golang 中,数组、字符串和切片的使用非常广泛,因此理解和掌握它们的基本操作和语法非常重要。同时,也需要了解它们在 Golang 中的特点和优势,例如切片可以避免数组长度不足或过长的问题,字符串可以直接使用Unicode 编码等。
来源:https://juejin.cn/post/7224759346747129913