【问题标题】:Method's application on copy of struct is mirrored in original struct [duplicate]方法在结构副本上的应用反映在原始结构中[重复]
【发布时间】:2018-01-31 19:27:39
【问题描述】:

我一直在通过构建一个小型线性代数库来使用 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 实现。我该如何解决呢?

经过测试的解决方案:

  1. Matrix.mat 确实是一个切片,我应该用copy(matB.mat, matA.mat 复制。但是,这不是唯一的问题,因为它仍在做同样的事情。

【问题讨论】:

  • 你的意思是copy()?你有一个切片,只需复制它。
  • 这不是一个切片,它是一个结构。忘记包含 BuildMatrix 函数,但基本上它会使用给定的行创建一个矩阵。
  • BuildMatrix 没有在代码中显示,但假设它返回一个指针,那么matAmatB 都是指向同一个对象的指针。与其说更改是“镜像”的,不如说它们是对完全相同对象的两个引用。
  • 编辑代码以包含函数的标题。 BuildMatrix 不返回指针。其实matAmatB在不同的内存位置。
  • @mariohm1311: Matrix.mat 是一个切片,您需要复制该切片。

标签: go memory methods struct copy


【解决方案1】:

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

切片是数组段的描述符。它由指向数组的指针、段的长度和它的容量(段的最大长度)组成。

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

【讨论】:

  • 哦,明白了。来自高级语言,这些东西一直让我着迷……有什么办法可以避免每次都手动复制?
  • 我不知道
  • 刚刚测试,并没有解决问题。问题出在与此相关的某个地方,但这不是复制切片的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-20
  • 1970-01-01
  • 1970-01-01
  • 2016-08-13
相关资源
最近更新 更多