gpt4 book ai didi

function - 在结构上调用函数的正确习惯用法是什么?

转载 作者:数据小太阳 更新时间:2023-10-29 03:06:08 26 4
gpt4 key购买 nike

我是新手(来自 python 和 ruby​​),想知道在结构上调用函数的惯用方式是什么?

主要是我想知道我是否应该使用点运算符来调用函数或使用我的类型作为参数之一。还是用指针更好?

  • 有指针还是没有指针?
  • 点与论点?*

我可以这样做吗?

package main

import "fmt"

func main() {
me := Person{firstname: "John", lastname: "Doe", age: 40}
fmt.Println(me.fullname())
}

type Person struct {
firstname string
lastname string
age int
}

func (p Person) fullname() string {
return p.firstname + p.lastname
}

或者这样

package main

import "fmt"

func main() {
me := Person{firstname: "John", lastname: "Doe", age: 40}
fmt.Println(fullname(&me))
}

type Person struct {
firstname string
lastname string
age int
}

func fullname(p *Person) string {
return p.firstname + p.lastname
}

最佳答案

没有一种正确的方法可以做到这一点。了解两者之间的差异并在适当的地方应用它们很重要。此外,您的功能并没有真正的可比性。在一种情况下,您已经定义了一个具有类型为 Person 的接收者的函数,并且它是按值传递的,这意味着创建了一个实例副本并将其压入堆栈。在另一种情况下,该函数是独立的,您将 Person 引用传递给它。您还可以通过将接收类型设为指针来使用“实例方法”按引用传递。

所以在第一种情况下;

func (p Person) fullname() string {
return p.firstname + p.lastname
}

你调用像 p.fullname() 这样的函数,然后 p 的副本被压入堆栈。如果在这个函数中赋值,p不会被修改,作用域中的实例会被修改。因此,对于 setter 或任何旨在更改对象状态的函数,这根本不是一个选项。

为了详细说明我所说的备选方案,您可以改为这样做;

func (p *Person) fullname() string {
return p.firstname + p.lastname
}

它仍然允许您在像 p.fullname() 这样的实例上调用它,但是,传递给该函数的是 *Person 类型的引用。因此,这将是实现在结构上设置值的函数的典型选择。

现在是你的第二个例子;

func fullname(p *Person) string {
return p.firstname + p.lastname
}

没有接收器并传递一个指针。这意味着您可以这样调用它 fullname(p)。该函数未导出,因此它仅在声明它的包中可用,在本例中为 main。为了与(可能)更熟悉的语言相提并论,这就像在 C++ 中定义一个函数,而其他两个在类中定义“方法”或函数。另外两个将与“按值传递”或“按引用传递”进行比较。这通过引用传递,不与任何类型相关联。

在您的示例中,出于性能原因,我将始终使用 func (p *Person) fullname() string。在我看来,使用按值传递替代方案 func (p Person) fullname() string 的最合适时机是当您想要强制执行不变性时。如果您想在生成一个新对象而不是修改现有对象的地方进行操作(很多集合库都是这样操作的,例如 C# 中的 LINQ 总是生成一个新集合并尝试在查询期间修改该集合将导致异常)那么您可能需要一个值类型接收器。

希望对您有所帮助。如果这仍然是造成混淆的原因,我可以更新更多信息。

关于function - 在结构上调用函数的正确习惯用法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37446501/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com