在Go语言中,可以通过返回指针或传递引用来实现对变量的传递。

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

golang: return a pointer or pass a reference

问题

构建一个对象的最佳方法是什么?

让我写一些代码:

type Car struct {
   Wheels int
   Doors  int
} 

这些汽车以某种方式存储在某个地方。那么我的接口应该是这样的类型:

func (s Store) GetCar() *Car

还是应该这样做:

func (s Store) GetCar(*Car)

并传递一个变量的引用?

我正在寻找一些经验法则。

谢谢!

英文:

What is the best way to "build" an object.

Leme write some code:

type Car struct {
   Wheels int
   Doors  int
} 

This cars are stored somewhere, somehow. So should my interface be the type of

func (s Store) GetCar() *Car

or should I make it

func (s Store) GetCar(*Car)

and pass a reference to a variable?

Im looking for some sort of rule of thumb.

Thanks!

答案1

得分: 17

Go管理堆/栈,跟踪引用何时超出作用域。因此,您可以放心地返回指针。

func (s *Store) GetCar() *Car {
    return &Car{Store: s}
}
英文:

Go manages the heap/stack, keeping track when the reference goes outside of scope. So, you can return the pointer without any worries.

func (s *Store) GetCar() *Car {
    return &Car{Store: s}
}

答案2

得分: 14

在许多情况下,这种方式更可取:

func (s Store) GetCar() *Car

因为它更方便和可读,但也有一些后果。所有的变量,比如Car,都是在函数内部创建的,这意味着它们被放置在堆栈上。在函数返回后,这段堆栈上的内存被标记为无效,并且可以再次使用。对于指针值(如*Car),情况略有不同。因为指针实际上意味着你想与其他作用域共享该值并返回一个地址,所以该值必须存储在某个地方,以便在调用函数时可用。它被复制到堆内存中,并在垃圾回收找不到对它的引用时保留在那里。

这意味着有一些开销:

  • 从堆栈复制值到堆
  • 垃圾回收的额外工作

如果值相对较小,这些开销并不显著。这就是为什么我们必须在io.Readerio.Writer中传递参数,而不是在返回值中拥有该值的原因。

如果你想深入了解,请参考以下链接:
Language Mechanics On Stacks And Pointers

Bad Go: pointer returns

英文:

In many cases this is preferable

func (s Store) GetCar() *Car

because it is more convenient and readable, but has consequences. All variables such as Car are created inside the function which means they are placed onto stack. After function return this memory of stack is marked as invalid and can be used again. It a bit differs for pointer values such as *Car. Because pointer is virtually means you want to share the value with other scope and return an address, the value has to be stored somewhere in order to be available for calling function. It is copied onto heap memory and stays there until garbage collection finds no references to it.

It implies overheads:

  • copying values from stack to heap
  • additional work for garbage collection

The overheads is not significant if the value is relatively small. This is a reason why we have to pass an argument in io.Reader and io.Writer rather than have the value in return.

If you'd like to dive yourself into guts follow the links:
Language Mechanics On Stacks And Pointers
and
Bad Go: pointer returns

答案3

得分: 5

最常见的方法是将其写成:

func (s Store) GetCar() *Car

或者,如果你不想使用指针,可以这样写:

func (s Store) GetCar() Car

另一种选择是将其写成GetCar(aCar *Car),这可能有效,但不够清晰,因为不明显aCar应该为空,然后由函数填充。

英文:

The most common way to do that would be to write it as:

func (s Store) GetCar() *Car

Or, if you don't want to use pointers, you can do it like:

func (s Store) GetCar() Car

The other alternative, making it GetCar(aCar *Car) might work, but it will not be as clear since it's not obvious that aCar should be sent empty and then populated by the function.

答案4

得分: -1

从一开始就使用new在堆上创建它们。

英文:

Create them on heap from beginning by new.

huangapple
  • 本文由 发表于 2017年6月29日 21:54:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/44827175.html
匿名

发表评论

匿名网友

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

确定