如何使用指针方法初始化指针接收器?
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 :(得分:7)
在调用.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()
函数,因此在函数外部它没有任何效果。
答案 1 :(得分: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
是一个空字符串,可能也可能没有。
答案 2 :(得分: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>
答案 3 :(得分:0)
NewPerson
函数可以初始化为个人,也不能使用Person的struct和Born方法来获取新的Person。
package main
import (
"fmt"
"time"
)
type Person struct {
Name string
Dob time.Time
}
func NewPerson(name string, year, month, day int) *Person {
return &Person{
Name: name,
Dob: time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.Local),
}
}
func (p *Person) GetAge() string {
d := time.Since(p.Dob)
return fmt.Sprintf("%s's age is %d", p.Name, int(d.Hours()/24/365))
}
func (p *Person) Born() {
p.Name = "New born (unnamed)"
p.Dob = time.Now()
}
func main() {
joe := NewPerson("Joe", 1999, 12, 31)
joeAge := joe.GetAge()
fmt.Println(joeAge)
newPerson := &Person{}
newPerson.Born()
newPersonAge := newPerson.GetAge()
fmt.Println(newPersonAge)
}