2017-03-17 35 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>