通向Golang的捷径【7. 数组和 slice】

2023-10-27

从本章开始, 将学习一些可包含一组元素的数据结构, 也被称为数据集合, 比如数组 (切片,slice) 和 map, 这很显然是受到 Python 语言的影响.

数组类型会使用[ ] 符号, 这也是大多数编程语言的基本类型, Go 语言的数组与其他语言基本类似, 但也有自己的一些特点, 它不具备 C 数组的动态特性, 如果需要类似功能, 需使用 Go 语言的 slice 类型, 该类型是一种基于 Go 数组类型的上层类型, 数组类型可包含存储空间, 但是不够灵活, 所以在 Go 代码中较少使用, 通常情况下, 都会使用 slice 类型, 该类型更易用且功能更强大.

7.1 声明和初始化

7.1.1 概念

数组是一个定长的数据元素序列, 同时所有数据元素的类型都相同, 并能使用任意类型, 比如整型, 字符串或用户自定义类型, 数组长度必须由一个常量表达式提供, 并且必须是一个非负的整型值, 在编译期内, 需对数组的所有元素值进行初始化.

数组元素的类型也可使用空接口 (参见 11.9 节), 只是在使用这些元素值时, 需提供一次类型断言 (类型检查),参见 11.3 节.

通过数组索引 (位置信息), 可访问和修改数组元素值, 索引值将从 0 开始, 即第一个元素的索引值为 0, 第二个元素的索引值为 1, 依次类推, 数组元素的个数, 被称为数组的长度或尺寸, 在数组声明时, 数组长度必须是一个常量 (以便在编译期内, 为数组分配内存), 最大的数组长度为 2Gb.

数组的声明格式为:
在这里插入图片描述
下图给出了数组的存储方式:
在这里插入图片描述
在声明数组时, 所有元素值都将自动初始化为对应类型的默认值, 如果是 int 类型, 元素值将自动初始化为 0.len(arr1) 可获取 arr1 数组的长度, 即为 5, 因此该数组的索引范围为 0 ∼ len(arr1)-1. arr1[0] 可获取数组的第一个元素, arr1[2] 可获取数组的第三个元素, 因此 arr1[i] 可获取索引值为 i 的元素值, 获取最后一个元素, 可使用 arr1[len(arr1)-1].

使用索引值, 可为数组元素分配一个数值, 如 arr[i] = value, 同时数组只接受有效索引值, 如果给出的索引值大于或等于 len(arr1), 如果被编译器检测到, 它将产生一个错误信息, 告知索引值超出了数组边界, 如果未被编译器检测到, 将在程序执行时, 导致运行崩溃, 参见第 13 章.
在这里插入图片描述
由于存在索引值, 可使用 for 语句对数组进行处理:
• 初始化数组元素
• 打印数组元素
• 连续处理每个数组元素

例 7.1 for_arrays.go

在这里插入图片描述
注意 for 语言中, i < len(arr1) 和 i <= len(arr1) 之间的区别, 在数组处理中, 也可使用 for-range:
在这里插入图片描述
其中 i 为数组的索引值, 同时 for 语句也可用于 slice 类型, 参见 7.2 节.

由于 Go 数组是一个数值类型 (不同于 C/C++ 可使用指针, 访问数组的第一个元素), 因此也可使用 new() 函数, 创建一个 Go 数组:
在这里插入图片描述
arr1 与 arr2 的区别在于,arr1 的元素类型为 *int, 而 arr2 的元素类型为 int. 如果将数组分配给其他数组, 将生成原数组的一个内存副本, 如下:
在这里插入图片描述
arr2 元素值将变更为 arr1 元素值, 在之后的语句中, 修改 arr2 元素值, 并不会导致 arr1 元素值的变更.

同时数组也可作为实参, 传递给函数, 如 func1(arr1), 这时也将创建原数组的一个副本, func1 也无法对原数组进行修改. 为了实现更高效的处理方法,arr1 可使用 &, 将引用传递给函数, 如func1(&arr1),

例 7.2 for_arrays.go

在这里插入图片描述
在这里插入图片描述
同时创建基于数值的 slice 也可使用上述方法, 也能将 slice 传递给函数, 参见 7.1.4 节.

7.1.2 数组的构造器

如果需要预先定义数组的元素值, 可使用{,} 组合符号完成定义, 这被称为数组的构造器, 而不是采用 [索引值]= 元素值, 进行每个元素的初始化, 而 Go 语言中, 所有复合类型都可使用类似的构造器, 完成所有元素的初始化.

例 7.3 array_literals.go

在这里插入图片描述
在 arrAge 数组定义中, 由于给出了对应的元素值, 可忽略 [5]int, 如果数组定义为 [10]int { 1, 2, 3 }, 等于提供了索引值 0-2 的元素值, 而后续的元素值将初始化为 0.

在 arrLazy 数组定义中, 编译器将获取{} 中元素值的个数, 以确定数组的长度. 同时 […]int 并不是一种类型,所以它是非法的, 应写为:
在这里插入图片描述
如果… 被忽略, 数组定义将被视为 slice 定义.

在 arrKeyValue 数组定义中, 只给出了索引值为 3 和 4 的元素值, 其他元素将初始化为空串, 从输出结果可查看该数组的初始化, 同时数组长度也可写为… 或是直接忽略. 同时也可获取新创建数组的指针, 即数组的访问地址, 如下:

例 7.4 pointer_array2.go

在这里插入图片描述
在这里插入图片描述
几何坐标 (或称之为矢量) 也将是数组应用的经典示例, 为了简化代码, 可使用该类型假名:
在这里插入图片描述

7.1.3 多维数组

数组通常是一个一维数组, 同时也可组合为多维数组, 比如:
在这里插入图片描述
内层数组通常会包含相同的长度, 而 Go 语言的多维数组将呈现一个矩形分布, 同时 slice 类型将是一个例外,参见 7.2.5 节.

例 7.5 multidim_array.go

在这里插入图片描述

7.1.4 将数组传递给函数

如果将大型数组传递给函数, 将会造成内存用量的快速上升, 可使用两种方法, 解决这类问题:
• 可传递数组的指针
• 使用数组的 slice 类型

以下示例将使用第一种方法.

例 7.6 array_sum.go

在这里插入图片描述
在这里插入图片描述
上述方法并不是 Go 语言的推荐方式, 可选择第 2 种解决方法, 即 slice 类型, 参见 7.2.2 节.

7.2 slice

7.2.1 概念

一个 slice 可引用数组的连续单元 (它必须基于数组, 且通常是匿名), 所以 slice 是一种引用类型 (其实它更类似于 C/C++ 的数组类型, 或是 Python 的 list 类型),slice 可以包含整个数组, 也可使用自定义的起始索引和结束索引, 设定数组的一个子集 (slice 结束索引的元素值, 不会包含在 slice 中), 同时 slice 可基于数组类型, 实现动态操作. 使用 len() 函数也可获取 slice 的长度 (元素个数).

同一元素的 slice 索引值, 将小于数组索引值, 与数组不同,slice 的长度可在代码执行过程中发生变化, 其最小长度可为 0, 最大长度可为数组长度, 因此 slice 是一个变长数组.

cap() 内建函数可获取 slice 的最大长度, 假定 s 是一个 slice,cap(s) 将基于 slice 在下层数组所处的位置, 计算slice 起始索引与下层数组末尾索引值之间的长度, 而 slice 长度无法超过 cap(s), 因此以下的判断条件都为真:0 <= len(s) <= cap(s).

如果多个 slice 来自于同一个数组, 它们之间可共享数据, 而多个数组之间不可能共享数据, 所以来自于同一个数组的多个 slice, 将给出相同的存储数据, 而数组之间的存储数据都是独立的.

由于 slice 是引用类型, 因此不会消耗额外的内存, 所以它比数组的效率更高, 同时 Go 代码将会更多地使用slice.

slice 的声明格式:
在这里插入图片描述
未初始化的 slice 将设定为 nil 值 (默认值), 同时它的初始长度为 0.

slice 的初始化格式:
在这里插入图片描述
它可表示数组 arr1 的一个切片 (从索引值 start 开始, 到 end-1 结束), 而 start:end 被称为切片表达式, 如果slice1[0] == arr1[start] 的比较结果为真, slice 可包含整个数组,slice 无法获取 slice1[0] 之前的内存数据, 这也是非法的!

声明语句var slice1 []type = arr1[:] 表示 slice1 将包含整个 arr1 数组, 而 arr1[:] 为 arr1[0:len(arr1)] 的简写, 也可使用另一种初始化方式, 实现相同的功能, slice1 = &arr1. arr1[2:] 等同于 arr1[2:len(arr1)], arr1[:3] 等同于arr1[0:3], 如果 slice1 只需保存最后一个元素, 可使用 slice1 = slice1[:len(slice1)-1], 基于包含三个元素的数组,

而创建一个 slice, 可使用 s := [3]int1,2,3[:] 或是 s := […]int1,2,3[:], 也可简化为 s := []int1,2,3.s2 := s[:] 可基于一个 slice 创建一个新 slice, 这两个 slice 将包含相同的元素, 并会引用同一个数组. 同时一个slice 可扩展到最大尺寸,s = s[:cap(s)], 如果设定的最大尺寸高于基础数组的长度, 将产生一个运行时错误, 参见例 7.7. 任意 slice(包括字符串 slice) 都满足以下条件:
在这里插入图片描述
同时 slice 也可使用与数组一样的初始化方法:var x = []int{2, 3, 5, 7, 11}, 上述语句将创建一个包含 5 个元素的数组, 之后再创建一个引用该数组的 slice.

在内存中,slice 将给出 3 个数据域, 首个数据域将指向下层数组, 其次是 slice 的长度, 之后是 slice 的容量, 如果 slice 为var x := []int{2, 3, 5, 7, 11} 和 y := x[1:3], 可得到以下的存储格式:
在这里插入图片描述

例 7.7 array_slices.go

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如果 s2 是一个 slice, 如果需要去除 s2 的首个元素, 可使用 s2 = s2[1:], 这时 s2 的结尾元素不会变化, 同时 s2的长度将减 1,slice 只能实现正向移动, 如果使用 s2 = s2[-1:] 语句, 将产生一个编译错误. 因此 slice 无法给出一个负值, 以访问 slice 在初始化时, 所隐藏的数组元素. 注意, 无法在 slice 中使用指针, 因为它已经是一个引用类型, 也就是一个指针.

7.2.2 将 slice 传递给函数

如果函数需要处理一个数组, 通常情况下, 应当选择 slice, 当函数调用时, 将创建一个数组切片, 并将该 slice传递给函数, 比如在函数中, 实现数组元素的累加和.
在这里插入图片描述

7.2.3 使用 make() 创建 slice

如果未定义下层数组, 这时可使用 make() 函数, 同时创建下层数组和 slice, 如:
在这里插入图片描述
len 为数组长度, 也是 slice 的初始长度, 使用上述方法, 可创建一个 slice s2, s2 := make([]int, 10), 并能满足条件cap(s2) == len(s2) == 10. make 函数包含了两个形参, 一是 slice 的数值类型, 二是 slice 的长度.

如果 slice 并未包含整个数组, 可增加一个形参 cap, 以确定 slice 的最大长度, 如:
在这里插入图片描述
下图描述了 make 函数创建的 slice 的存储格式:
在这里插入图片描述

例 7.8 make_slice.go

在这里插入图片描述
在这里插入图片描述
由于字符串本身就是一个字节数组, 因此也给出 slice 类型.

7.2.4 new() 与 make() 的区别

这两个函数都可在分配堆 (heap) 内存, 并可用于不同任务和使用不同类型.
• new(T) 可为 T 类型的一个元素, 分配存储空间 (初始值为 0), 并返回存储地址, 其中的类型为 *T, 可表
示一个指针, 将指向新分配的 T 类型存储空间, 这类分配可用于数组和结构 (参见第 10 章), 并可等价于&T{}.
• make(T) 它可返回 T 类型的初始值, 只能用于 3 种引用类型:slice,map 和 channel, 参见第 8 章和第 13 章.

下图将给出上述两种函数的分配结果:
在这里插入图片描述
与上图对应的代码如下:
在这里插入图片描述
上述用法在 Go 代码很少见到, 而p := make([]int, 0) 将创建一个已初始化的 slice, 该 slice 将指向一个为空的数组. 但 make 函数的常见用法如下:
在这里插入图片描述
上述代码可分配一个包含 50 个 int 元素的数组, 并创建一个 slice v, 它的长度为 10, 容量为 50, 且引用了下层数组的前 10 个元素.

7.2.5 多维 slice

除了使用一维数组和 slice 之外, 还将其组合成多维数组和 slice, 那么这种类型的长度变化更大, 所以 Go 语言中多维 slice 的维度变化, 将呈现逐步增大的态势, 同时内层 slice 必须单独分配 (使用 make).

7.2.6 bytes 包

在 bytes 包中, 字节 slice 是一种常见类型, 其中的函数都会使用这种类型, 这与 strings 包很相似 (参见 4.7节), 同时还包含了一种更方便的类型 Buffer:
在这里插入图片描述
在 Read 和 Write 方法中, 需要一个尺寸可变的缓冲, 因为读写操作中, 需要处理的字节数据的长度, 无法事先知道.
• 创建一个 Buffer 变量: var buffer bytes.Buffer
• 使用 new 函数, 创建一个 Buffer 变量指针: var r *bytes.Buffer = new(bytes.Buffer)
• 缓冲空间的创建函数: func NewBuffer(buf []byte) *Buffer

使用上述操作, 都可创建和初始化一个新的 Buffer 变量, 同时变量还可包含初始值, 使用 NewBuffer 创建的缓冲, 最好只用于读取操作.

使用缓冲, 实现字符串的合并

这类功能与 Java 语言的 StringBuilder 类很相似, 创建一个缓冲, 使用 buffer.WriteString(s) 方法, 可将每个字符串都附加到缓冲中, 之后可使用 buffer.String(), 将缓冲内容转换成一个字符串, 如下:
在这里插入图片描述
上述操作相比于 +=, 需要较多的内存, 同时对 CPU 性能也有要求, 尤其是需合并的字符串较多时.

7.3 for-range 控制结构

该结构可用于数组和 slice:
在这里插入图片描述
ix 为数组或 slice 的索引值,value 为索引对应的存储值, 在 for 语句的程序块中, ix 和 value 将视为本地变量,同时 value 将会给出一个副本, 因此 for 语句无法对 value 进行修改.

例 7.9 slices_forrange.go

在这里插入图片描述

例 7.10 slices_forrange2.go, 其中将对字符串进行处理

在这里插入图片描述
上例中, _ 可弃用索引值, 如果只需要索引值, 可忽略之后的存储值, 如下:
在这里插入图片描述
如果需要对 seasons[ix] 进行修改, 可使用上述代码. 使用嵌套的 for 循环, 可简单实现矩阵结构的处理, 如下:
在这里插入图片描述

7.4 slice 变量的尺寸修改

从之前的讨论中可知,slice 通常比下层数组更小, 如:
在这里插入图片描述
其中 start_length 为 slice 的长度, 而 capacity 通常是下层数组的长度, 这里有一种方法, 可使 slice 变更为最大尺寸 (capacity). 例如 slice1 = slice1[0:end], 其中 end 表示结束索引值 (下层数组的长度).

sl = sl[0:len(sl)+1] 可使 slice 尺寸加 1, 但 slice 尺寸的扩展, 不能超过下层数组的长度.

例 7.11 reslicing.go

在这里插入图片描述
在这里插入图片描述
另一个常见的示例:
在这里插入图片描述

7.5 slice 类型的复制与合并

为了给出 slice 的最大长度, 必须创建一个新的更大的 slice, 并可复制原始 slice 的数据, 以下代码将创建的一个副本, 同时新值将附加到原有值之后.

例 7.12 copy_append_slice.go

在这里插入图片描述

func append(s[]T, x …T) []T

append 函数可将零个或多个数值, 附加到 slice 中, 之后可返回实现合并的 slice, 同时类型也为 s 相同, 元素值类型也与 T 相同, 如果 s 的容量导致无法包含更多的数值, 则会分配一个新的更大的 slice, 并会将原有数值和附加值, 放入新 slice 中, 而新 slice 将引用另一个下层数组,append 函数通常都会成功, 除非 PC 机产生内存不足的问题.

如果需要将 slice y 附加到 slice x 上, 则需在 append 的形参列表中, 扩展出第二个形参, 如x = append(x, y…).

append 的应用很广泛, 如果需要完全控制相关处理, 可使用 AppendByte 函数:
在这里插入图片描述

func copy(dst, src []T) int

copy 函数可将一组类型为 T 的 slice 元素, 从源 slice 复制到目的 slice, 并覆盖掉目的 slice 的原有元素, 并能返回完成复制的元素个数, 这时源 slice 和目的 slice 的元素将重叠在一起, 而可复制的元素个数, 必须是源slice 和目的 slice 的最小存储单位, 如果源 slice 是一个字符串, 那么元素值的类型应为 byte, 如果需要对源slice 实现连续处理, 可在复制后, 给出 src = dst 语句.

7.6 字符串, 数组与 slice 的用法

7.6.1 从字符串中创建 slice

如果 s 是一个字符串 (等同于一个 byte 数组),c 是一个 byte slice, 可使用 c:=[]byte(s) 创建 c, 同时也可使用copy 函数,copy(dst []byte, src string), 甚至可使用 for-range 结构:

例 7.13 for_string.go

在这里插入图片描述
从上例可知,Unicode 字符将包含了 2 个字节, 而有些字符则会包含 3 个或 4 个字节, 如果出现错误的 UTF-8编码, 即使字符将设定为 U+FFFD, 但索引值只能提供一个字节的数据, 因此需进行转换 c:=[]int(s), 以使每个 int 类型中, 都可提供 Unicode 码, 即字符串的每个字符都可获得对应的整型值, 同时也可转换成 rune 格式r:=[]rune(s).

使用 len([]int(s)) 可获取字符串的字符个数, 但 utf8.RuneCountInString(s) 的执行速度更快.

一个字符串也可附加到一个 byte 类型的 slice 中, 如下:
在这里插入图片描述

7.6.2 从字符串中创建子串

substr := str[start:end] 可从 str 字符串中, 创建一个子串, 同时 start 和 end 提供了 str 字节数据的索引值,而 str[start:] 将使用 start 索引值至末尾索引值 (len(str)–1) 之间的字节数据, 创建一个子串,str[:end], 则可使用起始索引值 (0) 至 end 索引值之间的字节数据, 创建一个子串.

7.6.3 字符串与 slice 的存储

在内存中, 一个字符串将包含两个 word(16 个字节), 其中一个 word 包含了字串指针, 另一个 word 提供了字串长度, 如下图, 而字串指针在 Go 代码中不可见, 因此在大多数情况下,string 被视为一种数值类型, 也就是一个字符数组, 下图给出了字符串 string s = ”hello” 和子串 t = s[2:3] 的存储格式:
在这里插入图片描述

7.6.4 修改字符串的字符

在 Go 代码中, 字符串无法直接修改, 这意味着无法利用索引值, 对字符串进行左侧赋值, str[i] = ‘D’, 这时即使 i 是一个有效索引值, 也将产生一个错误:cannot assign to str[i].

为了实现字符串的修改, 首先需将字符串转换成一个 byte 数组, 之后基于索引值, 对数组进行修改, 再后 byte数组必须转换成一个新的字符串, 如下代码可将”hello” 修改为”cello”,
在这里插入图片描述
因此 slice 类型的字符串更容易使用.

7.6.5 byte 数组的比较函数

以下的 Compare 函数可返回两个 byte 数组的比较结果, 两个 byte 数组将以字母次序逐个比较元素值. 而返回结果为:
• 如果 a == b, 将返回 0
• 如果 a < b, 将返回-1
• 如果 a > b, 将返回 1
在这里插入图片描述

7.6.6 slice 和数组的搜索和排序

sort 包提供了搜索和排序的常用功能, 为了实现 int 类型 slice 的排序, 可导入 sort 包, 并调用函数 sort.Ints(arri),即 func Ints(a []int), 而 arri 为数组或 slice,Ints 函数可实现数组或 slice 的升序排列, 为测试排序结果, 可使用func IntsAreSorted(a []int) bool, 基于该函数的返回值 (true,false), 可判断排序是否成功.

如果元素类型为 float64, 可选择 func Float64s(a []float64), 如果元素类型为字符串, 可选择 func Strings(a []string).

为实现数组或 slice 的搜索, 必须首先完成数组或 slice 的排序 (因为搜索函数使用了二分搜索算法), 之后可选择 SearchInts(a []int, n int) int, 它可在 slice a 中搜索 n, 并可返回 n 的索引值, 而 float64 和 string 类型都有对应的函数:
在这里插入图片描述
sort 包的更多细节, 可查看网页http://golang.org/pkg/sort/. 同时在 11.6 节中, 还将讨论 sort 包的用法, 以及自行实现一个搜索函数.

7.6.7 append 函数

在 7.5 节中引入了 append 函数, 以下将给出 append 的不同用法:
在这里插入图片描述
在这里插入图片描述
使用 slice 和 append 函数, 可调整元素的次序, 一个 slice 经常被称为矢量, 以适应数学应用的语境, 为了简化代码, 可为 slice 定义一个假名 vector, 例 10.11(method2.go) 给出了一个简单示例.

如果读者需要了解 Go 语言的复杂应用, 可查看 Eleanor McHugh 编写的包文件, 在以下网页中可找到这些包文件:
• http://github.com/feyeleanor/slices
• http://github.com/feyeleanor/chain
• http://github.com/feyeleanor/lists

7.6.8 slice 与垃圾收集

slice 需指向下层数组, 在之前的示例中, 下层数组都比 slice 大得多, 当 slice 与下层数组建立引用关系后, 下层数组将保存在内存中, 直到它不再需要, 因此有时会出现一类情况, 即程序存储的所有数据中, 只有一小部分被使用.

比如 FindDigits 函数, 它可将一个文件载入内存, 并搜索第一个出现的连续数字, 还可基于这些数字生成一个新 slice 并返回.
在这里插入图片描述
上述代码可返回, 文件包含的 []byte, 这是一个 slice, 由于 slice 需引用原始的下层数组, 这时 slice 的引用, 将导致垃圾收集器无法释放该数组, 同时之前的整个文件也必须保存在内存中.

为了处理该问题, 需在返回之前, 将有用信息复制到一个新 slice 中, 如下:
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通向Golang的捷径【7. 数组和 slice】 的相关文章

随机推荐

  • Cause: com.mysql.cj.jdbc.exceptions.CommunicationsException: The last packet successfully.....

    最近将之前的项目部署到了服务器之后 发现在长时间不访问网站后 再次打开页面会出现白屏现象 除非重新刷新页面 否则无法正常加载数据 使用F12查看请求返回的JSON数据发现提示内部错误 由此可知问题在服务端 服务器相关信息 OS CentOS
  • Spring cloud Alibaba 之 分布式链路追踪 sleuth

    什么是链路追踪 微服务之间相互调用 每一个请求过来可能调用多个服务 比如 一个请求调用A 服务 A 又依赖B 服务 B又依赖C 服务 这样形成一个调用链 当我们查询日志的时候都需要知道一个请求的完整路径 这个时候链路追踪就产生作用 A 调用
  • 学python心得体会800字-浅谈我对python的学习感受

    python是一门非常有潜力的高级语言 历经多年的发展 其在编程上发挥着越来越大的作用 在这学期中 通过选修python课上的基础知识学习 我对python也有了一定的认识 而且 在字符串上的处理 python相对于c语言也是给程序员极大的
  • k8s 部署 jenkins

    一 前提条件 1 安装helm 二 安装harbor 1 添加harbor helm仓库 helm repo add jenkins https charts jenkins io 2 更新仓库 helm repo update
  • 什么是UE像素流送,像素流推流是什么原理?

    游戏开发者通常在运行游戏逻辑时会将游戏渲染到屏幕的同一台设备上来运行虚幻引擎应用 多人联网游戏可能会在应用程序的多个实例之间分发部分游戏逻辑 但每个单独的实例仍然会为自己的玩家在本地渲染游戏 即使是使用 HTML5 部署选项创建可以在 We
  • 【C/C++】读取字符串的多种方式(带空格)

    获取字符 字符串对象 字符串行的多种方式 Created By Liu Xianmeng On 2022 12 10 include
  • Linux逻辑卷管理(LVM)

    一 逻辑卷 LV 卷组 VG 物理卷 PV 关系 逻辑卷 LV 是卷组 VG 的一部分 可以在卷组大小内动态增加 每个卷组可分为多个逻辑卷 卷组由多个物理卷 PV 组成 每个物理卷是一个块设备 磁盘分区等 二 LVM存储 1 准备物理设备
  • VSCode自动格式化Vue代码

    VSCode自动格式化Vue代码 Prettier Code formatter 配置代码格式化文件 配置setting json VsCode关于Vue的格式化插件非常多 网上的资料也五花八门 可以使用的非常少 经过多次探索 终于找到一个
  • 剑指offer第45题:扑克牌顺子

    剑指offer第45题 扑克牌顺子 题目描述 扑克牌顺子 源码 题目描述 扑克牌顺子 LL今天心情特别好 因为他去买了一副扑克牌 发现里面居然有2个大王 2个小王 一副牌原本是54张 他随机从中抽出了5张牌 想测测自己的手气 看看能不能抽到
  • python,tensorflow,keras,pandas,numpy版本不匹配的问题(已解决)

    事情的起因 因为自己手残 更新了我搭建的tensorflow虚拟环境中numpy的版本 更高 导致import pandas 时出现版本不匹配的问题 于是将pandas一起更新 这时 pandas和numpy可以使用 但是由于tensorf
  • Linux 学习笔记2 常用命令

    Linux 学习笔记1 安装linux详细教程 O丶ne丨柒夜的博客 CSDN博客 查看使用7007端口的进程 ps aux grep 7007 Linux 目录结构 基本介绍 1 liux的文件系统是采用级层式的树状目录结构 在此结构中的
  • 五种边缘检测算法(附代码)

    一 Roberts 边缘检测算子 Roberts边缘检测算子根据任意一对互相垂直方向上的差分可用来计算梯度的原理 采用对角线方向相邻两像素之差 即 然后根据式 1 9 2 计算出Roberts的梯度幅度值 它们的卷积算子为 Roberts检
  • mysql tmp下#sql_xxx_0.MYD 类文件占满空间的经历

    作为一名全职运维 随时会碰到各种问题 今天晚上收到紧报警 一台数据库服务器磁盘空间使用快速从80 使用率到90 我们的数据库都是 gt 2T的磁盘 意识到这肯定是比较严重问题马上上线处理 状况如下 root mysql node1 tmp
  • 实用高效的寻路算法——A*寻路算法的实现及优化思路

    前言 寻路是游戏比较重要的一个组成部分 因为不仅AI还有很多地方 例如RTS游戏里操控人物点到地图某个点 然后人物自动寻路走过去 都需要用到自动寻路的功能 本文将介绍一个经常被使用且效率理想的寻路方法 A 寻路算法 并且提供额外的优化思路
  • CMake中list的使用

    CMake中的list命令用于列表操作 其格式如下 Reading list LENGTH
  • Windows部署Alpaca-lora

    Alpaca Lora 是一个轻量级的语言模型 可以实现基本的语言类对话 本文先后在两台机器上进行了配置 行文旨在介绍将此模型部署至Windows系统上时所遭遇的各种困扰 机器1配置 NVIDIA TITAN Xp 机器2配置 RTX309
  • Spring是什么?

    什么是Spring 我知道你现在可能迫不及待地想要开始编写Spring应用了 我向你保证 在本章结束之前 你肯定能够开发一个简单的Spring应用 但首先 我将使用Spring的一些基础概念为你搭建一个舞台 帮助你理解Spring是如何运转
  • ubuntu下nginx停止、启动、重启

    转载自 https www cnblogs com xiaoL p 6964217 html nginx s reload 修改配置后重新加载生效 nginx s reopen 重新打开日志文件 nginx t c path to ngin
  • python标书制作辅助docx

    from docx import Document def handle path r d a docx 表格在哪个位置 文件路径 document Document path 读入表格文件 tables document tables 获
  • 通向Golang的捷径【7. 数组和 slice】

    从本章开始 将学习一些可包含一组元素的数据结构 也被称为数据集合 比如数组 切片 slice 和 map 这很显然是受到 Python 语言的影响 数组类型会使用 符号 这也是大多数编程语言的基本类型 Go 语言的数组与其他语言基本类似 但