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

'VAR 사람이 * Person'는 이해가되지 않습니다. 'Person'은 구조체입니다. – Gravy

+1

@Gravy 물론 이치에 맞습니다. 'Person'을'Person' 구조체에 대한 초기화되지 않은 포인터로 정의합니다. 이 경우 OP가 원하는 것은 아닙니다. – Flimzy

+0

'person '에 대한 포인터를 가진'person'은 0 값으로 초기화됩니다 -'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() 기능으로 범위가 지정되어 있으므로 기능 밖에서 아무 효과가 없습니까?

type Person struct { 
    name string 
    age int 
} 

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

person := NewPerson("John Doe") 

일반적으로, 그들의 "제로 소위 있도록하는 방식 에있는 당신의 유형을 정의하려고하는 것이 좋습니다 것 :

+0

답장을 보내 주셔서 대단히 감사합니다. – Francis

1

나는 당신이 대신해야 할 것은"생성자 "또는"공장 "기능이라고 생각 값 "— 값이이 유형의 변수가 명시 적으로 초기화되지 않은 경우 가져옵니다. 그렇지 않으면 —이 바로 준비됩니다. 을 바로 사용할 수 있습니다. 의 0 값이 0이라는 적절한 값을 갖기 때문에 Person의 0 값이 의미있는 지 여부는 의심 스럽습니다. 및 name은 괜찮을 수도 있고 그렇지 않을 수도 있습니다.

+0

Kostix에 감사드립니다. 내 질문은 순전히 교육적이었고 공장 패턴이 갈 길이라는 것을 알고 있습니다. – Francis

1

분명히 personBorn 메서드로 초기화되지 않습니다. 매개 변수는 매개 변수에 인수를 할당하여 값으로 전달됩니다.

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>