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?

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
", bob)
}

This illustrates that methods are attributed to an instance of a particular type.

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.