```go
package model
//A Person class below
//关于包内标识符的可见性,如果以大写字母开头,那么这个标识符对于其他包来说就是可见的,小写则不可见
type Person struct{//一个结构体
longId int;//包外不可见
name string;//包外不可见
age int;//包外不可见
}
func NewPerson(longId int64,name string,age int) *Person{//一般的会提供这样一个方法用于构建对象返回对象指针
return &Person{longId:longId,name:name,age:age}
}
//一般面向对象会这样写,(person *Person)代表这个方法接受*person指针
func (person *Person) SetId(longId int) {
person.longId=longId;
}
//面向过程的写法会这样:上下两个方法实际上在执行的时候并没有什么区别,和Java this指针首先压栈的操作就是一样的;
func SetId2(person *Person,longId int){//SetId2()避免方法名冲突
person.longId=longId;
}
func (person *Person) SetName(name string){
person.name = name;
}
func (person *Person) SetAge(age int){
person.age = age;
}
func (person Person) SetAge2(age int){
person.age = age;
}
//main usage of Person
package main
import (
"model"
"fmt"
)
func main(){
var person *model.Person = new(model.Person);//内建函数new()返回一个类型的指针,这个类型的全部的field都回被初始化默认的值:0,false,"",nil
fmt.Println("person1 *person = ",person);
fmt.Println("========================================");
person2:=model.Person{};//{}一个类型的构造函数
fmt.Println("person2 person = ",person2);
person.SetAge2(11);
fmt.Println("After SetAge2,person2 person = ",person2);
person2.SetAge(11);//这里应该编译不过去啊,因为SetAge接收的是*Person类型,而person2是Person类型,然而却没有问题,这是Golang设计的问题么?
fmt.Println("After SetAge,person2 person = ",person2);
fmt.Println("========================================");
person3:=model.NewPerson(10,"person3",10);//更常用的方式
fmt.Println("person3 *person = ",person3);
person3.SetAge2(11);//这里应该编译不过去啊,因为SetAge接收的是Person类型啊,person3是*Person类型,这是Golang设计的问题么?
fmt.Println("After SetAge2,person3 *person = ",person3);
person3.SetAge(11);
fmt.Println("After SetAge,person3 *person = ",person3);
fmt.Println("========================================");
//person3:=model.Person{10,"person3",100};//注意Person内的field都是invisible的,编译时会报错,尽管IDE可能不会报错;
}
输出:
person1 *person = &{0 0}
========================================
person2 person = {0 0}
After SetAge2,person2 person = {0 0}
After SetAge,person2 person = {0 11}
========================================
person3 *person = &{10 person3 10}
After SetAge2,person3 *person = &{10 person3 10}
After SetAge,person3 *person = &{10 person3 11}
========================================
//考虑到golang的参数传递都是值传递(不论是struct还是基本类型还是pointer类型),SetAge和SetAge2在参数压栈的时候做了什么操作么?类似于Java里面的基本类型及包装类的自动转换?
```
第 1 条附言 ·
站长,int64 粘贴完后怎么有的变成int了 ,还有就是星(*)号也是有的丢有的不丢,奇怪,
@polaris
原来是编译器在编译阶段自己做了一些修改操作;
var p1 *Person,p1.SetAge2()在编译时会修改成*p1.Clone().SetAge2();//应该是有Clone这一步操作的。
var p2 Person,p2.SetAge()在编译时会修改成&p2.SetAge();
这不是瞎搞么?在编译后可执行文件和源代码的定义都不一致了;
#5
更多评论
并不是这一段有疑问;
有疑问的地方在:SetAge和SetAge2 按照方法的定义,SetAge 压栈时一部压入 *Person类型,而SetAge2 压栈时必须压入Person类型,
在上面代码person2.SetAge(11)和person3.SetAge2(11)编译或者运行时应该报错,我认为应该报错的原因正如注释缩写;
然而结果却没有,然后就可是迷惑了.
#2