2017-03-17 116 views
3

如何用指针方法初始化指针接收器?用指针方法初始化指针接收器进入

package main 

import "fmt" 

type Person struct { 
    name string 
    age int 
} 

func (p *Person) Born() { 

    if nil == p { 
     p = new(Person) 
    } 

} 

func main() { 

    var person *Person 
    person.Born() 
    if person == nil { 
     fmt.Println("This person should be initialized. Why is that not the case?") 
    } 
    fmt.Println(person) 
} 

人们会期望人于调用.Born()方法,它是一个指针接收器之后被初始化(清零)。但事实并非如此。有人可以对此有所了解吗?

+0

'变种人* Person'没有意义。 'Person'是一个结构体。 – Gravy

+1

@Gravy肯定是有道理的。它将'person'定义为一个未初始化的指向'Person'结构体的指针。这不是OP在这种情况下想要的。 – Flimzy

+0

'具有'指向Person'类型的'person'被初始化为零值 - 'nil' –

回答

4

在调用指针接收器的.Born()方法后,人们会期待被初始化(归零)。

在接收方上调用方法假定接收方已经初始化。

所以,你需要初始化:

var person *Person 
person = &Person{} // Sets the pointer to point to an empty Person{} struct 

或者在单个语句:

var person = &Person{} 

或者简写:

person := &Person{} 

的原因,你打算自初始化失败:

func (p *Person) Born() { 
    if nil == p { 
     p = new(Person) 
    } 
} 

是否您的新作业为p的作用范围为Born()函数,因此在函数之外它不起作用。

+0

非常感谢您的回复。 – Francis

1

我认为你需要,而不是什么是“构造”或“工厂”功能:

type Person struct { 
    name string 
    age int 
} 

func NewPerson(name string) *Person { 
    return &Person{ 
     name: name, 
    } 
} 

person := NewPerson("John Doe") 

一般情况下,它的建议,试图以这样的方式 使他们所谓的“零定义你的类型值“—当这个 类型的变量没有明确初始化时,它会得到一个值,否则—准备好立即使用 。 在你的情况下,Person的零值是否为 是合理的,因为它将有age为0,这是非常合理的, 和name是一个空字符串,它可能会也可能不会。

+0

谢谢Kostix。我的问题纯粹是教育,我意识到工厂模式是要走的路。 – Francis

1

很明显,person不会被方法Born初始化。通过参数赋值给参数传递参数。

The Go Programming Language Specification

该类型的方法是与接收机作为 第一个参数的函数的类型。

type Point struct{ x, y float64 } 

func (p *Point) Scale(factor float64) { 
    p.x *= factor 
    p.y *= factor 
} 

例如,Scale有方法类型

func(p *Point, factor float64) 

然而,一个函数声明这种方式是不是方法。

在函数调用中,函数值和参数按照通常顺序在 中计算。评估完成后,呼叫 的参数将按值传递给函数,被调用的函数将开始执行 。当函数返回时,函数的返回参数通过值 传回给调用函数。

为了说明,这里有各种形式的Born方法调用。 p的范围仅限于方法或函数调用。

package main 

import "fmt" 

type Person struct { 
    name string 
    age int 
} 

// Method 
func (p *Person) Born() { 
    if nil == p { 
     p = new(Person) 
    } 
} 

// Method as function 
func Born(p *Person) { 
    if nil == p { 
     p = new(Person) 
    } 
} 

func main() { 

    // Initial method call form 
    { 
     var person *Person 
     person.Born() 
     fmt.Println(person) 
    } 

    // Equivalent method call by value form 
    { 
     var person *Person 
     { 
      p := person 
      p.Born() 
     } 
     fmt.Println(person) 
    } 

    // Equivalent method call as function call form 
    { 
     var person *Person 
     { 
      p := person 
      Born(p) 
     } 
     fmt.Println(person) 
    } 

    // Equivalent method call as inline function form 
    { 
     var person *Person 
     { 
      p := person 
      if nil == p { 
       p = new(Person) 
      } 
     } 
     fmt.Println(person) 
    } 

} 

输出:

<nil> 
<nil> 
<nil> 
<nil>