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
}