英文:
Golang: Method expressions instances of Object
问题
我正在为golang中的构造函数构建一个可变参数函数,并遇到了一个有趣的问题。第一个函数是有效的,但不是我想要的方式。而第二个函数则无效。你有什么想法为什么会这样?
英文:
I'm trying to build a variadic function for a constructor in golang and I've ran into an interesting issue. This function is working...
package main
import "fmt"
type person struct {
name string
}
// This is working, but a really Not how I want to do this
func personConstructor(params ...string) person {
name := "Unnamed Person" // Default name
if len(params) > 0 {
name = params[0]
}
return person{name: name}
}
func main() {
bob := personConstructor("Bob")
}
https://play.golang.org/p/dcAdHEQtYz
And yet this, isn't.
package main
import "fmt"
type person struct {
name string
}
// This isn't working
func (p person) constructor(params ...string) person {
name := "Unnamed Person" // Default name
if len(params) > 0 {
name = params[0]
}
return person{name: name}
}
func main() {
bob := person.constructor("Bob")
}
https://play.golang.org/p/YiTQctu-1A
Any idea as to why this is?
答案1
得分: 4
你的问题与可变参数无关。
你需要阅读并学习方法表达式:
https://golang.org/ref/spec#Method_expressions
package main
type person struct {
name string
}
func (p person) constructor(params ...string) person {
name := "Unnamed Person" // 默认名称
if len(params) > 0 {
name = params[0]
}
return person{name: name}
}
func main() {
// 这样是可以的
person.constructor(person{}, "Bob")
}
这段代码可以编译通过,但在你的情况下,这样做没有太多意义。构造函数期望一个 person 接收器。无论你是在之前写 person{}.constructor("bob")
还是在之后写 person.constructor(person{}, "bob")
,都没有关系。构造函数期望一个 person 接收器。构造函数方法不是“某个 person 命名空间的字段”,这不是 JavaScript。
如果你想编写一个构造函数,可以写一个没有接收器的工厂函数:
func NewPerson(params ...string) *Person {
// 代码
}
这是 Go 中的惯用方式。
我建议你至少阅读一次规范。
英文:
Your problem has nothing to do with variadics.
You need to read and learn about method expressions :
https://golang.org/ref/spec#Method_expressions
package main
type person struct {
name string
}
func (p person) constructor(params ...string) person {
name := "Unnamed Person" // Default name
if len(params) > 0 {
name = params[0]
}
return person{name: name}
}
func main() {
// THIS WORKS
person.constructor(person{},"Bob")
}
This compiles but it makes very little sense to do that in your case. the constructor function expect a person receiver. Whether you put it before like
like person{}.constructor("bob")
or after like person.constructor(person{},"bob")
doesn't matter. constructor expects a person receiver . constructor method is not a "field of some person namespace", this isn't javascript.
If you want to write a constructor function write a factory without a receiver
func NewPerson(params...string)*Person{
// code
}
that's the idiomatic way to do that in Go.
I suggest you to go through the spec once at least.
答案2
得分: 3
在Go之旅的介绍中对你的问题给出了简明的答案。
> Go语言没有类的概念。但是,你可以在类型上定义方法。
你的示例假设constructor
函数在person
结构体的定义中被定义。但事实并非如此。方法是在类型的实例上操作的,这个类型被称为接收者。在这种机制下,构造函数是不可能的。Go社区中已经形成了一种惯例,即使用工厂函数来初始化结构体,你的第一个函数定义就是一个例子。
第二个示例失败是因为constructor
期望在一个未定义的person
实例上调用。如果你构造一个person
结构体的新实例,该函数将按预期工作。
// https://play.golang.org/p/5XDGSTMVj9
func (p person) constructor(params ...string) person {
name := "Unnamed Person" // 默认名称
if len(params) > 0 {
name = params[0]
}
return person{name: name}
}
func main() {
// 让我们定义一个person结构体的新实例
p := person{}
// 当在实例上调用该函数时,它按预期工作
bob := p.constructor("Bob")
fmt.Printf("%+v\n", bob)
}
这说明方法是归属于特定类型的实例的。
英文:
The introduction in the Go tour provides a concise answer to your question.
> Go does not have classes. However, you can define methods on types.
Your examples assume that the constructor
function is defined on the definition of the person
struct. This is not the case. A method operates on an instance of a type referred to as a receiver. A constructor is not possible in this mechanism. The established pattern within the Go community is to use a factory function to initialize a struct and is exemplified in your first function definition.
The second example provided is failing because constructor
is expecting to be called on an instance of a person which is undefined. If you construct a new instance of a person
struct the function behaves as expected.
// https://play.golang.org/p/5XDGSTMVj9
func (p person) constructor(params ...string) person {
name := "Unnamed Person" // Default name
if len(params) > 0 {
name = params[0]
}
return person{name: name}
}
func main() {
// Lets define a new instance of a person struct
p := person{}
// The function, when called on a instance, works as expected
bob := p.constructor("Bob")
fmt.Printf("%+v\n", bob)
}
This illustrates that methods are attributed to an instance of a particular type.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论