使用指针或值嵌入Go

zer*_*ing 24 go

我可以用指针和值嵌入golang.通过指针

type Bitmap struct{
    data [4][4]bool
}

type Renderer struct{
    *Bitmap
    on uint8
    off uint8
}
Run Code Online (Sandbox Code Playgroud)

按价值

type Bitmap struct{
    data [4][4]bool
}

type Renderer struct{
    Bitmap 
    on uint8
    off uint8
}
Run Code Online (Sandbox Code Playgroud)

什么更喜欢指针或价值?

rog*_*rog 25

这取决于.这里有几种可能性.

  • 如果Renderer按值传递并且Bitmap上需要的方法在*Bitmap上定义,那么您需要嵌入*Bitmap.
  • 如果Renderer作为指针传递,那么您可以将Bitmap作为值嵌入而没有任何问题(在这种情况下仍然可以访问指针方法).
  • 如果Bitmap具有返回指针的构造函数,并且Bitmap的零值不可用,则您需要嵌入*Bitmap,因为您不希望鼓励对Bitmap值进行按值复制.
  • 如果所有Bitmap方法都是值方法,那么您肯定希望按值嵌入.

在这里的特定情况下,我可能会按值嵌入,因为类型很小 - 它为您提供了访问位置和更少的内存分配.


thw*_*hwd 8

通过嵌入您通常希望从呼叫转发中受益的类型.*Bitmap方法集是一个超集的Bitmap方法集.所以在大多数情况下你会想要嵌入*Bitmap,除非它的所有方法都有一个类型的接收器Bitmap或方法设置为空,在这种情况下你可以避免间接.


小智 5

如罗格的回答所示,似乎对接收者有误解。方法(接收方)不是在指针或类型上“定义的”,可以在类型值上调用与该指针相同的方法,接收方的签名仅确定接收的是类型值还是指向类型价值。也就是说func(t *YourType),可以要求YourType&YourType反之亦然与值传感器。我认为这应该澄清一下:https//play.golang.org/p/AT1J2oGkum 关于是嵌入值还是指针的问题...引用性实际上取决于您如何处理外部对象,如果将指针传递给外部结构,则可以访问相同的嵌入式结构值,如果要传递外部结构的值,是否要使其指向嵌入式结构或副本的“原始”基础值?我认为在大多数情况下,您要么希望嵌入一个指针并将指针传递给外部结构,要么会嵌入一个值并传递外部结构的值。


jam*_*lee 5

我试过:https : //play.golang.org/p/IVM5OoDU9ZN

package main

import (
    "fmt"
)

type Base struct {
    Name string
}

func (b Base) PrintName() {
    fmt.Println(b.Name)
}

func (b *Base) PrintNameP() {
    fmt.Println(b.Name)
}

func (b Base) ChangeName(name string) {
    b.Name = name
}

func (b *Base) ChangeNameP(name string) {
    b.Name = name
}

type EmbedsBase struct {
    Base
}

type EmbedsPointerToBase struct {
    *Base
}

func main() {

    fmt.Println("")
    fmt.Println("# embed by value and refrenced by value, not change origianl value")
    b := Base{"Jeff Hardy"}
    eb := EmbedsBase{b}
    eb.PrintName()
    eb.ChangeName("John Cena")
    eb.PrintName()

    fmt.Println("")
    fmt.Println("# embed by value, but refrenced by pointer, changed origianl value")
    b = Base{"Jeff Hardy"}
    ebp := &EmbedsBase{b}
    ebp.PrintNameP()
    ebp.ChangeNameP("John Cena")
    ebp.PrintNameP()

    fmt.Println("")
    fmt.Println("# embed by pointer, but refrenced by value, not chage origianl value")
    b = Base{"Jeff Hardy"}
    epb := EmbedsPointerToBase{&b}
    epb.PrintName()
    epb.ChangeName("John Cena")
    epb.PrintName()

    fmt.Println("")
    fmt.Println("# embed by pointer, and refrenced by pointer, changed origianl value")
    b = Base{"Jeff Hardy"}
    epbp := &EmbedsPointerToBase{&b}
    epbp.PrintNameP()
    epbp.ChangeNameP("John Cena")
    epbp.PrintNameP()
}
Run Code Online (Sandbox Code Playgroud)

上面的结果是:

# embed by value and refrenced by value, not change origianl value
Jeff Hardy
Jeff Hardy

# embed by value, but refrenced by pointer, changed origianl value
Jeff Hardy
John Cena

# embed by pointer, but refrenced by value, not chage origianl value
Jeff Hardy
Jeff Hardy

# embed by pointer, and refrenced by pointer, changed origianl value
Jeff Hardy
John Cena
Run Code Online (Sandbox Code Playgroud)