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

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
", t1, t2)
    t1.Val = -10
    t1.Values[1] = 200
    fmt.Printf("t1: %v, t2: %v
", t1, t2)
}

prog.go:17: cannot convert t1 (type *MyType1) to type MyType2
prog.go:17: invalid indirect of MyType2(t1) (type MyType2)

Your code would compile with just

t2 = (*MyType2)(t1)

http://play.golang.org/p/lUGo-mxAOa

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
", myInts, myInts, myIntsArr, myIntsArr, myIntsArr.Sum())
    for i, _ := range myInts {
        fmt.Printf("myInt: %v, %p, myIntsArr elem: %v, %p
", myInts[i], &myInts[i], myIntsArr[i], &myIntsArr[i])
    }
    myInts[0] = 100
    fmt.Printf("myInts: %v, %p, myIntsArr: %v, %p, Sum: %v
", myInts, myInts, myIntsArr, myIntsArr, myIntsArr.Sum())
    myIntsArr[1] = 200
    fmt.Printf("myInts: %v, %p, myIntsArr: %v, %p, Sum: %v
", 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.

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
", t1, t2)

    t1.Val = -10
    t1.Values[1] = 200
    fmt.Printf("t1: %v, t2: %v
", t1, t2)

    t2.Val = -20
    t2.Values[1] = 1.2345
    fmt.Printf("t1: %v, t2: %v
", 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]}