Gonum 在使用嵌入式结构时抛出坏区恐慌
Gonum throws bad region panic when using an embedded struct
我正在使用 gonum 执行一些线性代数计算。扩展原始 mat.VecDense
结构后,在对自身应用方法时出现 "bad region: identical" 恐慌。当我使用 gonum 提供的原始设置时,不会出现此错误。
这是我的实现:
type Vector struct {
mat.VecDense
}
func NewVector(n int, data []float64) *Vector {
return &Vector{*mat.NewVecDense(n, data)}
}
我正在使用以下代码片段对其进行测试:
func main() {
u, v := mat.NewVecDense(3, []float64{1, 2, 3}), mat.NewVecDense(3, []float64{4, 5, 6})
fmt.Printf("[U - NewVecDense]\tADDRESS: %v, VALUE: %v\n", &u, u)
fmt.Printf("[V - NewVecDense]\tADDRESS: %v, VALUE: %v\n", &v, v)
u.AddVec(u, v)
fmt.Println("-------------------------")
x, y := NewVector(3, []float64{1, 2, 3}), NewVector(3, []float64{4, 5, 6})
fmt.Printf("[X - NewVector]\tADDRESS: %v, VALUE: %v\n", &x, x)
fmt.Printf("[Y - NewVector]\tADDRESS: %v, VALUE: %v\n", &y, y)
x.AddVec(x, y)
fmt.Println(x)
}
虽然第一次添加执行正常,但第二次失败:
[U - NewVecDense] ADDRESS: 0xc42000c028, VALUE: &{{[1 2 3] 1} 3}
[V - NewVecDense] ADDRESS: 0xc42000c030, VALUE: &{{[4 5 6] 1} 3}
-------------------------
[X - NewVector] ADDRESS: 0xc42000c040, VALUE: &{{{[1 2 3] 1} 3}}
[Y - NewVector] ADDRESS: 0xc42000c048, VALUE: &{{{[4 5 6] 1} 3}}
panic: mat: bad region: identical
AddVec
是一个方法 implemented by gonum:
func (v *VecDense) AddVec(a, b Vector)
为什么会这样,请问正确的实现方式是什么?
编辑:
感谢@Himanshu 我设法解决了这个问题。
我为我正在使用的每个方法创建了传递方法,传递结构的正确级别:
type Vector struct {
*mat.VecDense
}
func NewVector(n int, data []float64) Vector {
return Vector{mat.NewVecDense(n, data)}
}
func (v *Vector) AddVec(a, b Vector) {
v.VecDense.AddVec(a.VecDense, b.VecDense)
}
func (v *Vector) SubVec(a, b Vector) {
v.VecDense.SubVec(a.VecDense, b.VecDense)
}
func (v *Vector) ScaleVec(alpha float64, a Vector) {
v.VecDense.ScaleVec(alpha, a.VecDense)
}
func (v *Vector) AddScaledVec(a Vector, alpha float64, b Vector) {
v.VecDense.AddScaledVec(a.VecDense, alpha, b.VecDense)
}
此外 - 我不确定这是否是正确的方法 - 我还将 NewVector
的 return 类型从指针更改为值,因为它包含指向mat.VecDense
无论如何。请注意 *mat.VecDense
满足来自 gonum 的 Vector
接口,因此将此内部字段传递给方法工作正常,如上例所示。
在 Golang 中,将提升的方法描述为
Promoted fields act like ordinary fields of a struct except that they
cannot be used as field names in composite literals of the struct.
给定结构类型 S 和定义类型 T,提升的方法包含在结构的方法集中,如下所示:
- 如果S包含嵌入字段T,则S和*S的方法集均包含接收者为T的提升方法。*S的方法集还包含接收者为*T的提升方法。
- 如果 S 包含嵌入字段 *T,则 S 和 *S 的方法集都包含接收者为 T 或 *T 的提升方法。
问题是您将指针类型参数传递给 AddVec
函数。但是在第二种情况下你使用的是指针类型字段。
func (v *VecDense) AddVec(a, b Vector)
需要注意的另一件事是 AddVec
具有 Vector
结构的值类型参数,但您将指针传递给 Vector
字段作为
x, y := NewVector(3, []float64{1, 2, 3}), NewVector(3, []float64{4, 5, 6})
在上面的代码中 x,y
是从 NewVector
返回的指针类型
x.AddVec(x, y)
问题是在进行阴影检测时比较指针。这是海事组织的一个错误。我刚刚提交 https://github.com/gonum/gonum/issues/945
我正在使用 gonum 执行一些线性代数计算。扩展原始 mat.VecDense
结构后,在对自身应用方法时出现 "bad region: identical" 恐慌。当我使用 gonum 提供的原始设置时,不会出现此错误。
这是我的实现:
type Vector struct {
mat.VecDense
}
func NewVector(n int, data []float64) *Vector {
return &Vector{*mat.NewVecDense(n, data)}
}
我正在使用以下代码片段对其进行测试:
func main() {
u, v := mat.NewVecDense(3, []float64{1, 2, 3}), mat.NewVecDense(3, []float64{4, 5, 6})
fmt.Printf("[U - NewVecDense]\tADDRESS: %v, VALUE: %v\n", &u, u)
fmt.Printf("[V - NewVecDense]\tADDRESS: %v, VALUE: %v\n", &v, v)
u.AddVec(u, v)
fmt.Println("-------------------------")
x, y := NewVector(3, []float64{1, 2, 3}), NewVector(3, []float64{4, 5, 6})
fmt.Printf("[X - NewVector]\tADDRESS: %v, VALUE: %v\n", &x, x)
fmt.Printf("[Y - NewVector]\tADDRESS: %v, VALUE: %v\n", &y, y)
x.AddVec(x, y)
fmt.Println(x)
}
虽然第一次添加执行正常,但第二次失败:
[U - NewVecDense] ADDRESS: 0xc42000c028, VALUE: &{{[1 2 3] 1} 3}
[V - NewVecDense] ADDRESS: 0xc42000c030, VALUE: &{{[4 5 6] 1} 3}
-------------------------
[X - NewVector] ADDRESS: 0xc42000c040, VALUE: &{{{[1 2 3] 1} 3}}
[Y - NewVector] ADDRESS: 0xc42000c048, VALUE: &{{{[4 5 6] 1} 3}}
panic: mat: bad region: identical
AddVec
是一个方法 implemented by gonum:
func (v *VecDense) AddVec(a, b Vector)
为什么会这样,请问正确的实现方式是什么?
编辑:
感谢@Himanshu 我设法解决了这个问题。
我为我正在使用的每个方法创建了传递方法,传递结构的正确级别:
type Vector struct {
*mat.VecDense
}
func NewVector(n int, data []float64) Vector {
return Vector{mat.NewVecDense(n, data)}
}
func (v *Vector) AddVec(a, b Vector) {
v.VecDense.AddVec(a.VecDense, b.VecDense)
}
func (v *Vector) SubVec(a, b Vector) {
v.VecDense.SubVec(a.VecDense, b.VecDense)
}
func (v *Vector) ScaleVec(alpha float64, a Vector) {
v.VecDense.ScaleVec(alpha, a.VecDense)
}
func (v *Vector) AddScaledVec(a Vector, alpha float64, b Vector) {
v.VecDense.AddScaledVec(a.VecDense, alpha, b.VecDense)
}
此外 - 我不确定这是否是正确的方法 - 我还将 NewVector
的 return 类型从指针更改为值,因为它包含指向mat.VecDense
无论如何。请注意 *mat.VecDense
满足来自 gonum 的 Vector
接口,因此将此内部字段传递给方法工作正常,如上例所示。
在 Golang 中,将提升的方法描述为
Promoted fields act like ordinary fields of a struct except that they cannot be used as field names in composite literals of the struct.
给定结构类型 S 和定义类型 T,提升的方法包含在结构的方法集中,如下所示:
- 如果S包含嵌入字段T,则S和*S的方法集均包含接收者为T的提升方法。*S的方法集还包含接收者为*T的提升方法。
- 如果 S 包含嵌入字段 *T,则 S 和 *S 的方法集都包含接收者为 T 或 *T 的提升方法。
问题是您将指针类型参数传递给 AddVec
函数。但是在第二种情况下你使用的是指针类型字段。
func (v *VecDense) AddVec(a, b Vector)
需要注意的另一件事是 AddVec
具有 Vector
结构的值类型参数,但您将指针传递给 Vector
字段作为
x, y := NewVector(3, []float64{1, 2, 3}), NewVector(3, []float64{4, 5, 6})
在上面的代码中 x,y
是从 NewVector
x.AddVec(x, y)
问题是在进行阴影检测时比较指针。这是海事组织的一个错误。我刚刚提交 https://github.com/gonum/gonum/issues/945