英文:
GoLang: Memory allocation for type inheritance and casting in Go
问题
在Go语言中,如果我有一个自定义类型,继承自一个整数切片,如果我将一个整数数组转换为我的自定义类型,是否会涉及新的内存分配?
对于切片来说,不会有内存分配,因为切片是指针类型。
但是我有一个更一般的问题。那么结构体呢?似乎会进行复制操作。
我正在尝试弄清楚是否可以将一个结构体指针转换为不同类型的指针。
在你提供的代码中,无法将t1(类型为*MyType1)转换为类型MyType2,因此会出现编译错误。
英文:
In Go if I have a custom type inherited from let's say a slice of integers if I cast an array of integers to my custom type would it involve new memory allocation?
http://play.golang.org/p/cNpKELZ3X- :
package main
import (
"fmt"
)
type MyIntsArray []int
func (a MyIntsArray) Sum() int {
sum := 0
for _, i := range a {
sum += i
}
return sum
}
func main() {
myInts := []int{1,2,3,5,7,11}
myIntsArr := MyIntsArray(myInts)
fmt.Println(fmt.Sprintf("myInts: %v, myIntsArr: %v, Sum: %v", myInts, myIntsArr, myIntsArr.Sum()))
}
Update: OK, for slices there is no memory allocation as slices are pointers.
But I have more general question. How about structs? Seems it makes copy: http://play.golang.org/p/NXgM8Cr-qj and it is because of working with value types.
I am trying to figure out if I can cast a pointer to a struct to a pointer of a different type. Something like this: http://play.golang.org/p/BV086ZAeGf
package main
import (
"fmt"
)
type MyType1 struct {
Val int
Values []int
}
type MyType2 MyType1
func main() {
t1 := &MyType1{Val: -1, Values: []int{1,3,5}}
var t2 *MyType2
t2 = *MyType2(t1)
fmt.Printf("t1: %v, t2: %v\n", t1, t2)
t1.Val = -10
t1.Values[1] = 200
fmt.Printf("t1: %v, t2: %v\n", t1, t2)
}
prog.go:17: cannot convert t1 (type *MyType1) to type MyType2
prog.go:17: invalid indirect of MyType2(t1) (type MyType2)
答案1
得分: 5
不,你将在同一块内存上工作。切片是指针,所以默认情况下,对切片的“复制”意味着复制地址本身,而不是该地址处的值。
http://play.golang.org/p/vy-c7sS9Fz
package main
import (
"fmt"
)
type MyIntsArray []int
func (a MyIntsArray) Sum() int {
sum := 0
for _, i := range a {
sum += i
}
return sum
}
func main() {
myInts := []int{1,2,3,5,7,11}
myIntsArr := MyIntsArray(myInts)
fmt.Printf("myInts: %v, %p, myIntsArr: %v, %p, Sum: %v\n", myInts, myInts, myIntsArr, myIntsArr, myIntsArr.Sum())
for i, _ := range myInts {
fmt.Printf("myInt: %v, %p, myIntsArr elem: %v, %p\n", myInts[i], &myInts[i], myIntsArr[i], &myIntsArr[i])
}
myInts[0] = 100
fmt.Printf("myInts: %v, %p, myIntsArr: %v, %p, Sum: %v\n", myInts, myInts, myIntsArr, myIntsArr, myIntsArr.Sum())
myIntsArr[1] = 200
fmt.Printf("myInts: %v, %p, myIntsArr: %v, %p, Sum: %v\n", myInts, myInts, myIntsArr, myIntsArr, myIntsArr.Sum())
}
正如你所看到的,每个元素的地址都是相同的,当你从一个变量中更改一个值时,另一个变量中的相同值也会发生变化。
英文:
No. You will work on the same memory. Slices are pointers, so the default "copying" of a slice means copying the address itself, not the value found at that address.
http://play.golang.org/p/vy-c7sS9Fz
package main
import (
"fmt"
)
type MyIntsArray []int
func (a MyIntsArray) Sum() int {
sum := 0
for _, i := range a {
sum += i
}
return sum
}
func main() {
myInts := []int{1,2,3,5,7,11}
myIntsArr := MyIntsArray(myInts)
fmt.Printf("myInts: %v, %p, myIntsArr: %v, %p, Sum: %v\n", myInts, myInts, myIntsArr, myIntsArr, myIntsArr.Sum())
for i, _ := range myInts {
fmt.Printf("myInt: %v, %p, myIntsArr elem: %v, %p\n", myInts[i], &myInts[i], myIntsArr[i], &myIntsArr[i])
}
myInts[0] = 100
fmt.Printf("myInts: %v, %p, myIntsArr: %v, %p, Sum: %v\n", myInts, myInts, myIntsArr, myIntsArr, myIntsArr.Sum())
myIntsArr[1] = 200
fmt.Printf("myInts: %v, %p, myIntsArr: %v, %p, Sum: %v\n", myInts, myInts, myIntsArr, myIntsArr, myIntsArr.Sum())
}
As you can see, all the addresses are identical for each element, and when you change one value from one variable item, the same value is available on the other.
答案2
得分: 2
你的代码只需要这样编译:
t2 = (*MyType2)(t1)
http://play.golang.org/p/lUGo-mxAOa
答案3
得分: 0
Go语言不支持不同结构体指针之间的类型转换。如果你真的想要进行类型转换,可以使用unsafe
包,其中包含特殊类型unsafe.Pointer
,它支持其他类型不支持的操作:
- 任何类型的指针值都可以转换为
Pointer
类型。 Pointer
类型可以转换为任何类型的指针值。uintptr
类型可以转换为Pointer
类型。Pointer
类型可以转换为uintptr
类型。
代码示例:
package main
import (
"fmt"
"unsafe"
)
type MyType1 struct {
Val int
Values []int32
}
type MyType2 struct {
Val int
Values []float32
}
func main() {
t1 := &MyType1{Val: -1, Values: []int32{1, 3, 5}}
p := unsafe.Pointer(t1)
var t2 *MyType2 = (*MyType2)(p)
fmt.Printf("t1: %v, t2: %v\n", t1, t2)
t1.Val = -10
t1.Values[1] = 200
fmt.Printf("t1: %v, t2: %v\n", t1, t2)
t2.Val = -20
t2.Values[1] = 1.2345
fmt.Printf("t1: %v, t2: %v\n", t1, t2)
}
运行该代码将输出:
t1: &{-1 [1 3 5]}, t2: &{-1 [1e-45 4e-45 7e-45]}
t1: &{-10 [1 200 5]}, t2: &{-10 [1e-45 2.8e-43 7e-45]}
t1: &{-20 [1 1067320345 5]}, t2: &{-20 [1e-45 1.2345 7e-45]}
英文:
Go doesn't support casting between pointers to different structs. If you really want to you can use unsafe
package which contains special type unsafe.Pointer
which supports operations that no other type does:
> - A pointer value of any type can be converted to a Pointer.
> - A Pointer can be converted to a pointer value of any type.
> - A uintptr can be converted to a Pointer.
> - A Pointer can be converted to a uintptr.
http://play.golang.org/p/fhOptEOQ74
package main
import (
"fmt"
"unsafe"
)
type MyType1 struct {
Val int
Values []int32
}
type MyType2 struct {
Val int
Values []float32
}
func main() {
t1 := &MyType1{Val: -1, Values: []int32{1,3,5}}
p := unsafe.Pointer(t1)
var t2 *MyType2 = (*MyType2)(p)
fmt.Printf("t1: %v, t2: %v\n", t1, t2)
t1.Val = -10
t1.Values[1] = 200
fmt.Printf("t1: %v, t2: %v\n", t1, t2)
t2.Val = -20
t2.Values[1] = 1.2345
fmt.Printf("t1: %v, t2: %v\n", t1, t2)
}
The code will print:
t1: &{-1 [1 3 5]}, t2: &{-1 [1e-45 4e-45 7e-45]}
t1: &{-10 [1 200 5]}, t2: &{-10 [1e-45 2.8e-43 7e-45]}
t1: &{-20 [1 1067320345 5]}, t2: &{-20 [1e-45 1.2345 7e-45]}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论