GoLang:Go中类型继承和类型转换的内存分配

huangapple go评论75阅读模式
英文:

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

英文:

Your code would compile with just

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]}

huangapple
  • 本文由 发表于 2016年4月15日 17:16:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/36643050.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定