This question already has answers here:
Concisely deep copy a slice?

(3个答案)


2年前关闭。




我一直在通过构建一个小的线性代数库来研究Go中的方法,但是我遇到了以下代码段的问题:
package main

import (
    "fmt"
)

type Matrix struct {
    mat    []float64
    nR, nC int
}

func (m Matrix) String() string { ... }

// EmptyMatrix initializes a nR*nC matrix to 0
func EmptyMatrix(nR, nC int) Matrix { ... }

// BuildMatrix creates a matrix build by its rows, and returns a Matrix
func BuildMatrix(rows ...[]float64) Matrix { ... }

// Set sets the value of mat[i,j] to val
func (m *Matrix) Set(i, j int, val float64) {
    if (i < m.nR) && (j < m.nC) {
        m.mat[i*m.nC+j] = val
    } else {
        panic(fmt.Sprintf("Index (%d,%d) out of range (0:%d,0:%d)",
                          i, j, m.nR, m.nC))
    }
}

func main() {
    matA := matrix.BuildMatrix([]float64{2, 3}, []float64{4, -5})
    matB := matA
    fmt.Println(matA)
    matB.Set(1,1,2)
    fmt.Println(matA)
    fmt.Printf("%p\n%p\n",&matA,&matB)
}

运行时,输出为:
[ [ 2.00 3.00 ]
  [ 4.00 -5.00 ] ]
[ [ 2.00 3.00 ]
  [ 4.00 2.00 ] ]
0xc04207c060
0xc04207c090

如果我更改matB中的值,则更改会反映在matA中,这不是我想要的。在Python中,我会首先制作一个matA的深层副本,但是我还没有找到Python的copy.deepcopy()函数的任何标准Go实现。我应该如何解决呢?

测试解决方案:
  • Matrix.mat确实是一个 slice ,我应该使用copy(matB.mat, matA.mat复制。但是,这不是唯一的问题,因为它仍在做同样的事情。
  • 最佳答案

    matA.matmatB.mat都指向同一位置。

    slice 是数组段的描述符。它由一个指向数组的指针,段的长度及其容量(段的最大长度)组成。
    https://blog.golang.org/go-slices-usage-and-internals

    复制该结构时,复制的结构包含指针的副本(指向相同的数组段)。
    参见https://play.golang.org/p/KUWq-dnGMRl
    你需要做

    matB.mat = make([]float64, len(matA.mat))
    copy(matB.mat, matA.mat)
    
    https://play.golang.org/p/ZlmFT8toj6A

    09-11 05:45