简体   繁体   English

去:我创造了太多的价值观吗?

[英]Go: Am I creating too many values?

If I have a struct like this 如果我有这样的结构

type myStruct struct {
    mystring string
    myint int
}

and if I have a function that returns a new myStruct like this 如果我有一个函数返回一个像这样的新myStruct

func New() myStruct {
    s := myStruct{}

    s.mystring = "string"
    s.myint = 1

    return s
}

Because I first store it in the "s" variable before returning it, is my function actually making 2 myStruct values instead of one? 因为我在返回它之前首先将它存储在“s”变量中,我的函数实际上是在制作2个myStruct值而不是一个吗?

And if so, is it then a better practice to make sure I don't first store it in the variable? 如果是这样,那么确保我不首先将其存储在变量中是一种更好的做法吗?

The return statement will return a copy of the myStruct object value. return语句将返回myStruct对象值的副本。 If it is a small object then this is fine. 如果它是一个小物体,那么这很好。

If you intend for the caller to be able to modify this object, and the struct will have methods that use a pointer as the receiver, then it makes more sense to return a pointer to your struct instead: 如果您打算让调用者能够修改此对象,并且struct将具有使用指针作为接收器的方法,那么返回指向结构的指针更有意义:

func New() *myStruct {
    s := myStruct{}

    s.mystring = "string"
    s.myint = 1

    return &s
}

You can see the copy happening when you compare the memory address of value vs pointer return types: http://play.golang.org/p/sj6mivYSHg 当您比较值的内存地址与指针返回类型时,您可以看到发生的副本: http//play.golang.org/p/sj6mivYSHg

package main

import (
    "fmt"
)

type myStruct struct {
    mystring string
    myint    int
}

func NewObj() myStruct {
    s := myStruct{}
    fmt.Printf("%p\n", &s)

    return s
}

func NewPtr() *myStruct {
    s := &myStruct{}
    fmt.Printf("%p\n",s)
    return s
}

func main() {

    o := NewObj()
    fmt.Printf("%p\n",&o)

    p := NewPtr()
    fmt.Printf("%p\n",p)
}


0xf8400235a0 // obj inside NewObj()
0xf840023580 // obj returned to caller
0xf840023640 // ptr inside of NewPtr()
0xf840023640 // ptr returned to caller

I'm definitely not a Go expert (or even novice :) ), but as @max.haredoom mentioned, you can allocate variables in the function signature itself. 我绝对不是Go专家(甚至是新手:)),但正如@ max.haredoom所提到的,你可以在函数签名本身中分配变量。 In that way, you can also omit the s in the return : 这样,您还可以省略returns

package main

import "fmt"

type myStruct struct {
    mystring string
    myint    int
}

func New() (s myStruct) {
    s.mystring = "string"
    s.myint = 1

    return
}

func main() {
    r := New()
    fmt.Println(r)
}

// Outputs {string 1}

In the examples that I have come across in Effective Go , it does seem to be the most common way of doing things of this nature, but again, I am definitely not an authority on the subject (and will look for additional info on the actual performance). 在我在Effective Go中遇到的例子中,它似乎是最常见的做这种事情的方式,但同样,我绝对不是这个主题的权威(并且会寻找关于实际的更多信息)性能)。

I think I found the answer by using defer. 我想我通过推迟找到了答案。

I updated the function so that there's a deferred modification to the myStruct value. 我更新了函数,以便对myStruct值进行延迟修改。 This means it will happen after the return, but before it is received on the other end. 这意味着它将在返回之后发生,但在另一端收到之前。

When I do this, the struct that is received by the caller does not show the updated value, so it appears as though I am indeed returning a copy. 当我这样做时,调用者接收的结构不显示更新的值,所以看起来好像我确实正在返回一个副本。

func New() myStruct {
    s := myStruct{}

    defer func() {
        s.mystring = "new value" // defer an update to the value
    }()

    s.mystring = "string"
    s.myint = 1

    return s
}

func main() {

    b := New()

    fmt.Println(b) // still shows the original value
}

http://play.golang.org/p/WWQi8HpDny http://play.golang.org/p/WWQi8HpDny

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM