【问题标题】:Strange Behavior of append in two dimension slice二维切片中追加的奇怪行为
【发布时间】:2020-08-02 05:15:11
【问题描述】:

我对 Go 语言有点陌生,并试图构建一个函数,它将一个切片细分为多个大小几乎相等的切片。如果主切片的大小不适合子切片的数量,我打算将剩余的元素按顺序重新分配到子切片。

我已经构建了以下代码:

package main

import (
    "fmt"
    stc "strconv"
    "strings"
)

func main() {
    myslice := make([]int, 12)
    myslice = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    fmt.Println("Original Slice = ", myslice)
    newdiv := subslices(myslice, 4)
    fmt.Println(newdiv)
}

func subslices(sl []int, dividnet int) [][]int {
    var res [][]int

    minsize := len(sl) / dividnet

    for i := 0; i < dividnet; i++ {
        res = append(res, sl[i*minsize:i*minsize+minsize])
    }

    for i := 0; i < dividnet; i++ {
        fmt.Printf("res[%d] = %v\n", i, res[i])
    }

     fmt.Println(res)
     if rem := len(sl) % dividnet; rem != 0 {
        fmt.Println("remaining elements = ", rem)
        for j := 0; j < rem; j++ {
            tobeadd := sl[minsize*dividnet+j]
            fmt.Println("element to be added = ", tobeadd)
            fmt.Printf("res[%d] before append = %v\n", j, res[j])
            res[j] = append(res[j], tobeadd)
            fmt.Printf("res[%d] after append = %v\n", j, res[j])
     }
     }
    return res
}
func gentwodim(x, y int) [][]int {
    res := make([][]int, x)
    for z := range res {
        res[z] = make([]int, y)
    }

    for i := 0; i < x; i++ {
        for j := 0; j < y; j++ {
            res[i][j] = i + j
        }
    }
    return res
}

Go Play 示例 sample of the above code


代码输出如下:

res[0] = [1 2]
res[1] = [3 4]
res[2] = [5 6]
res[3] = [7 8]
[[1 2] [3 4] [5 6] [7 8]]
remaining elements =  2
element to be added =  9
res[0] before append = [1 2]
res[0] after append = [1 2 9]  // up to this step the code works fine
element to be added =  10
res[1] before append = [9 4]   // I did not get why res[1] is changed by replacing 3 with 9
res[1] after append = [9 4 10]
[[1 2 9] [9 4 10] [10 6] [7 8]]

但是,在添加了res[0] after append = [1 2 9] 中显示的第一个剩余元素后,第二个子切片从res[1] = [3 4] 更改为res[1] before append = [9 4] 我试图调试并理解我在这里遗漏或编码错误的内容,但不能。

感谢您的支持。

【问题讨论】:

  • 这是因为切片有一个底层数组,如果将 myslice 切片成 4 个子切片,所有这些切片仍然具有相同的底层数组,它们只是“查看”数组的不同段。如果底层数组中有足够的空间,附加到这些子切片之一将更新底层数组中的元素。这里有效地流血到下一个子切片。
  • ...见这里play.golang.org/p/L0GyulibYB6,在附加到结果之前会创建一个子切片的副本,这样每个子切片都有自己的底层数组。
  • 如果你对细节感兴趣可以去这里:blog.golang.org/slices-intro
  • @mkopriva,非常感谢,您解决了这个问题。感谢您为纠正代码所做的努力。

标签: go slice


【解决方案1】:

通过在切片时分配“额外”值来避免问题:

func subslices(sl []int, dividnet int) [][]int {
    var res [][]int
    var i int
    for len(sl) > 0 {
        i = len(sl) / (dividnet - len(res))
        res = append(res, sl[:i])
        sl = sl[i:]
    }
    return res
}

【讨论】:

  • 感谢您的回答,但我相信为了避免流血到下一个元素,我需要独立拥有一个新的子切片。
猜你喜欢
  • 1970-01-01
  • 2016-12-06
  • 2019-12-13
  • 2020-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-21
  • 2020-03-27
相关资源
最近更新 更多