Golang:方法表达式的对象实例

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

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.

huangapple
  • 本文由 发表于 2016年9月27日 09:38:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/39714772.html
匿名

发表评论

匿名网友

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

确定