Go 展开一个切片';s大小以防止切片边界超出范围错误
我写了以下内容:Go 展开一个切片';s大小以防止切片边界超出范围错误,go,Go,我写了以下内容: func main() { //inside main fileInputBytes, err := ioutil.ReadFile("/tmp/test") byteSize2 := len(fileInputBytes) var inputFileByteSlice = fileInputBytes[0:] var numberOfIndexes = math.Floor(float6
func main() {
//inside main
fileInputBytes, err := ioutil.ReadFile("/tmp/test")
byteSize2 := len(fileInputBytes)
var inputFileByteSlice = fileInputBytes[0:]
var numberOfIndexes = math.Floor(float64(byteSize / indexingOffset))
for i := 1; i <= int(numberOfIndexes); i++ {
// adding i to the indexer insures that we use lookahed to ignore previously inserted indexing values
var v int = (i * indexingOffset) + i
Insert(&inputFileByteSlice, v+i, indexingByteValue)
fmt.Println(i)
}
}
//outside main
//variation of https://blog.golang.org/slices with pointers and such
func Insert(slice *[]byte, index int, value byte) {
// Grow the slice by one element.
(*slice) = (*slice)[0 : len(*slice)+1]
// Use copy to move the upper part of the slice out of the way and open a hole.
copy((*slice)[index+1:], (*slice)[index:])
// Store the new value.
(*slice)[index] = value
// Return the result.
}
func main(){
//内干管
fileInputBytes,err:=ioutil.ReadFile(“/tmp/test”)
byteSize2:=len(fileInputBytes)
var inputFileByteSlice=fileInputBytes[0:]
var numberOfIndexes=数学层(float64(字节大小/索引偏移))
对于i:=1;i首先,切片已经是引用类型。因此,如果不打算更改其容量,则无需传递其指针。因此,可以将main
简化为:
func main() {
fileInputBytes, err := ioutil.ReadFile("/tmp/test")
byteSize2 := len(fileInputBytes)
// No need to use pointer to slice. If you want a brand new slice
// that does not affect the original slice values, use copy()
inputFileByteArray := fileInputBytes
var numberOfIndexes = math.Floor(float64(byteSize / indexingOffset))
for i := 1; i <= int(numberOfIndexes); i++ {
var v int = (i * indexingOffset) + i
// Insert needs to return the newly updated slice reference
// which should be assigned in each iteration.
inputFileByteArray = Insert(inputFileByteArray, v+i, indexingByteValue)
fmt.Println(i)
}
}
这可能不是最好的实现,但它足够简单。示例用法如下:您的函数仅在片恰好具有足够的初始容量时工作。如果您需要更多容量,您只能使用append
函数“增长”片。您仍然可以使用*[]字节
指针参数,用于在适当位置修改切片,如下所示:
func Insert(slice *[]byte, index int, value byte) {
*slice = append(*slice, 0)
copy((*slice)[index+1:], (*slice)[index:])
(*slice)[index] = value
}
但是,更常见的做法是返回一个新的切片值,并每次重新分配它。这将为您提供一个与内置的append
类似的函数签名
func Insert(slice []byte, index int, value byte) []byte {
slice = append(slice, 0)
copy(slice[index+1:], slice[index:])
slice[index] = value
return slice
}
您正在将int
转换为float64
,然后对已经是偶数整数值的对象使用math.Floor
,然后将其转换回int
。所有这些都没有任何用处,只需使用原始的整数除法结果即可。@JimB很好的捕获,这对我来说相当业余。您不需要进行临时运算切片,切片插入的记录方法很好(如果愿意,可以保持短路)。我也不会接受无效的索引值并返回不正确的结果。索引超出范围应该会死机,或者至少会提供错误,而不是默默地创建错误的切片。@JimB您能解释一下为什么我最初尝试“增长”切片时没有实例化具有更大内存容量的新切片吗?@a思考一下我使用指针的原因对于原始的片,我想限制内存占用。你认为每次都不复制到新的片就可以扩展吗?此外,JimB声明可以不使用tmp声明。如果这是真的,我假设只声明:copy是可行的(tmp,片[:index+1])?Rice,因为你正在对数组进行随机插入,所以它总是线性时间。因为数组(或切片在这里)是连续的内存块,所以不能在中间插入一些东西,而不必将数组中的每个后续元素移到一个地方。因此,如果不需要随机访问,则需要进行广泛的复制。(即,切片元素访问始终是线性的,从开始到结束),您可以尝试使用链表类型的结构。此外,JimB的答案与我的答案类似,但更好地实现,因此,如果有必要,请使用它。@abhink非常感谢您提供的指导性示例/解释。您的逻辑非常有用(在您编写的第二个函数中),内存容量也会随着append的使用而增加?@Rice:我不知道你的意思。这两个函数基本相同,只是在调用方式上有所不同。对不起,我需要更具体一些。我的简单需求(最初)是为了增加片的实际内存容量,而不仅仅是长度。append能完成这项工作吗?@Rice:append就是这么做的。如果不增加容量,就不能将长度增加到超出容量。
func Insert(slice []byte, index int, value byte) []byte {
slice = append(slice, 0)
copy(slice[index+1:], slice[index:])
slice[index] = value
return slice
}