【问题标题】:GoLang: Memory allocation for type inheritance and casting in GoGoLang:Go 中类型继承和强制转换的内存分配
【发布时间】:2016-04-15 09:16:13
【问题描述】:

在 Go 中,如果我有一个从整数切片继承的自定义类型,如果我将整数数组转换为自定义类型,是否会涉及新的内存分配?

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()))
}

更新:好的,对于切片没有内存分配,因为切片是指针。

但我有更一般的问题。结构体呢?似乎它会复制:http://play.golang.org/p/NXgM8Cr-qj,这是因为使用值类型。

我试图弄清楚是否可以将指向结构的指针转换为不同类型的指针。像这样的东西: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)

【问题讨论】:

标签: go


【解决方案1】:

没有。您将使用相同的内存。切片是指针,因此切片的默认“复制”意味着复制地址本身,而不是在该地址找到的值。

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())
}

如您所见,每个元素的所有地址都是相同的,并且当您从一个变量项更改一个值时,另一个值将可用。

【讨论】:

  • 好的,切片是合理的。但我已经尝试过结构,似乎它确实创建了一个副本:play.golang.org/p/NXgM8Cr-qj
  • 在那个结构中你有一个切片,它是一个指针。这是同一件事。那片将是相同的。对于 int、float、string,复制值,对于 slice、map、pointer,复制指针的值/地址。您必须创建一个克隆函数,在其中创建一个带有新切片的新结构,然后为每个切片元素复制源结构切片中的值。
  • 等等,我可能误解了这个问题。 :) 你有一个指针转换。这是您在顶部评论的示例,而不是您在此处放置的评论。
  • 这是您的示例中出现错误的修复方法。您不能从指针转换为结构,您可以使用指针或非指针类型play.golang.org/p/0t_vBFGFaI
【解决方案2】:

您的代码只需编译即可

t2 = (*MyType2)(t1)

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

【讨论】:

  • 我喜欢堆栈溢出,这得到了两票和一个被接受的响应,而我得到了一票,同时解释了一些东西,并解决了你的问题。我想这就是我们生活的世界,每个人都只想复制粘贴代码而没有思考。祝你事业蒸蒸日上,op.
  • @Radoo 当然你的回答更全面。我现在就投票。
【解决方案3】:

Go 不支持在指向不同结构的指针之间进行强制转换。如果你真的想要,你可以使用 unsafe 包,其中包含特殊类型 unsafe.Pointer,它支持其他类型不支持的操作:

  • 任何类型的指针值都可以转换为指针。
  • 指针可以转换为任何类型的指针值。
  • uintptr 可以转换为指针。
  • 指针可以转换为 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)
}

代码将打印出来:

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

【讨论】:

    猜你喜欢
    • 2012-04-21
    • 2010-11-30
    • 1970-01-01
    相关资源
    最近更新 更多