[英]Initialize pointer receiver in pointer method Go
如何使用指针方法初始化指针接收器?
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()方法之后,人们会期望人被初始化(归零),这是一个指针接收器。 但事实并非如此。 有人可以对此有所了解吗?
在调用.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")
通常,建议尝试以这样的方式定义您的类型,以便它们所谓的“零值” - 这种类型的变量在未明确初始化时获得的值 - 可以立即使用。 在你的情况下,对于Person
的零值是否合理是值得怀疑的,因为它的age
为0,这是完全合理的,并且name
是空字符串,这可能是也可能不是。
显然, person
不会被Born
方法初始化。 通过赋值给参数的参数,通过值传递参数。
方法的类型是以接收者作为第一个参数的函数的类型。
type Point struct{ x, y float64 } func (p *Point) Scale(factor float64) { px *= factor py *= 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>
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)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.