Go语言里的struct在感觉上更像是Java中属于引用类型的对象。但事实并不是。
下面分别用代码来掩饰他们在传参上的区别。
// 定义User结构体
type User struct {
Name string
Age int
}
// 定义一个全局的user
var guser User = User {
"yyyy",
28,
}
// 定义一个函数,参数为User结构体“对象”,将全局guser指向传递过来的User结构体“对象”
func modifyUser(user User) {
fmt.Printf("参数user的地址 = %p\n",&user)
fmt.Printf("guser修改前的地址 = %p\n",&guser)
fmt.Println("guser修改前 = ",guser)
// 修改指向
guser = user
fmt.Printf("guser修改后的地址 = %p\n",&guser)
fmt.Println("guser修改后 = ",guser)
}
func main() {
var u User = User {
"xxxx",
29,
}
fmt.Printf("将要传递的参数u的地址 = %p\n",&u)
modifyUser(u)
}
执行结果:
将要传递的参数u的地址 = 0xc0000ac018
参数user的地址 = 0xc0000ac030
guser修改前的地址 = 0x51c080
guser修改前 = {yyyy 28}
guser修改后的地址 = 0x51c080
guser修改后 = {xxxx 29}
public class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String print() {
return "{name = " + name + ",age = " + age + "}";
}
}
public class Demo {
private static User guser = new User("yyyy",28);
public static void modifyUser(User user) {
System.out.println("参数user的地址 = " + user);
System.out.println("guser修改前的地址 = " + guser);
System.out.println("guser修改前 = " + guser.print());
guser = user;
System.out.println("guser修改后的地址 = " + guser);
System.out.println("guser修改后 = " + guser.print());
}
public static void main(String[] args) {
User u = new User("xxxx", 29);
System.out.println("将要传递的参数u的地址 = " + u);
modifyUser(u);
}
}
执行结果:
将要传递的参数u的地址 = com.example.User@7d2ac533
参数user的地址 = com.example.User@7d2ac533
guser修改前的地址 = com.example.User@4ef01483
guser修改前 = {name = yyyy,age = 28}
guser修改后的地址 = com.example.User@7d2ac533
guser修改后 = {name = xxxx,age = 29}
通过上述两个程序的执行结果可以分析出如下结论:
// 定义User结构体
type User struct {
Name string
Age int
}
// 定义一个函数,参数为User结构体“对象”,修改其Name字段
func modifyName(user User) {
fmt.Println("修改前user.Name = ",user.Name)
// 修改Name字段
user.Name = "yyyy"
fmt.Println("修改后user.Name = ",user.Name)
}
func main() {
var u User = User {
"xxxx",
29,
}
modifyName(u)
fmt.Println("执行修改函数后参数u.Name = ",u.Name)
}
执行结果:
修改前user.Name = xxxx
修改后user.Name = yyyy
执行修改函数后参数u.Name = xxxx
public class Demo {
private static User guser = new User("yyyy",28);
public static void modifyName(User user) {
System.out.println("修改前user.Name = " + user.getName());
user.setName("yyyy");
System.out.println("修改后user.Name = " + user.getName());
}
public static void main(String[] args) {
User u = new User("xxxx", 29);
modifyName(u);
System.out.println("执行修改函数后参数u.Name = " + u.getName());
}
}
执行结果:
修改前user.Name = xxxx
修改后user.Name = yyyy
执行修改函数后参数u.Name = yyyy
基于上面对对象赋值的理解,理解字段修改就更容易了:
既然Java传递的是引用,那我们也可以让Go传 指针(传递的是对象地址,指向的是同一个对象内存)来实现同样的效果:
// 定义User结构体
type User struct {
Name string
Age int
}
// 定义一个函数,参数为User结构体“对象指针”,修改其Name字段
func modifyNameByPointer(user *User) {
fmt.Println("修改前user.Name = ",(*user).Name)
// 修改Name字段
(*user).Name = "yyyy"
fmt.Println("修改后user.Name = ",(*user).Name)
}
func main() {
var u User = User {
"xxxx",
29,
}
modifyNameByPointer(&u)
fmt.Println("执行修改函数后参数u.Name = ",u.Name)
}
数组的情况和struct一样,最后的结论也可以参考上面[传对象]的结论,这里就不再赘述。感兴趣的也可以参考上面的程序自己验证一下。
相关代码请参考: