新人求教一个 Go 语言问题

328 天前
 jiekeop
package main

import "fmt"

type MyService struct {
	Name string
}

func (s *MyService) PName() {
	fmt.Printf("name1 	%s\n", s.Name)
	s.Name = "zhangsan"
	fmt.Printf("name2 	%s\n", s.Name)

}

func main() {
	var service MyService
	service.PName()
	fmt.Printf("name3 	%s\n", service.Name)
}
///output
name1   
name2   zhangsan
name3   zhangsan

代码很简单,无法理解的是 var service MyService 。根据我目前看的学习文档,这个只是声明了一个变量,其类型为 MyService ,而没有绑定到任何内存区域,为什么后续的方法调用没出现空指针报错呢.赋值 Name 也成功了。百思不得其解

1054 次点击
所在节点    程序员
12 条回复
zxdstyle
328 天前
renyijiu
328 天前
var 定义之后没有赋值,默认是一个 zero value, 其中 name 字段是 string ,所以是个空字符串。
serco
328 天前
没用过 go ,随便看了一下,你说的这句实际上已经是实例化了一个 struct

看这个的案例 https://www.tutorialsteacher.com/go/struct#:~:text=In%20Go%20lang%2C%20struct%20(structure,the%20type%20and%20struct%20keywords.

You can declare an instance and assign values later on using a dot, as shown below.

```
var s4 Student
s4.id = 4
s4.name = "Abdul"
s4.grade = 8

fmt.Println(s4) //output: {4 Abdul 8}

var s5 Student
s5.name = "Sachin"

fmt.Println(s5) //output: {0 Sachin 0}
```
NX2023
328 天前
在我的印象里声明一个变量的时候都会自动初始化为零值,完全不要操心
Nazz
328 天前
go 有空值安全特性
dobelee
328 天前
这个不是指针类型。下面这个才是。你的写法是初始化零值。
var service *MyService
moqimoqide
328 天前
帮问了一下 gpt:

在 Go 语言中,如果结构体类型的实例被声明为值类型变量(而不是指针类型变量)时,在调用该结构体类型的方法时,会自动进行值拷贝( pass by value )。换言之,值类型变量作为一个参数传递给方法时,方法会获取该值类型变量的一份拷贝,当方法需要修改该结构体类型实例的值时,它修改的只是拷贝中的相应值,而不是原来的变量。所以调用顺序如下:

1. 执行 service.PName() 方法时,会将 MyService 类型的 service 的一份拷贝传递给 PName() 方法。

2. 在 PName() 方法中,首先打印出 s.Name 的值,由于此时 Name 字段还没有被初始化,因此打印出的结果为空字符串。

3. 接下来,将 s.Name 的值更改为 "zhangsan"。

4. 继而,打印出 s.Name 的值,此时 Name 字段的值已经被更改为 "zhangsan",因此打印出的结果为 "zhangsan"。

5. PName() 方法执行结束,返回到 main() 函数中。

6. 在 main() 函数中,打印出 service.Name 的值,此时打印出的是 "zhangsan"。

因此,在你的代码中,var service MyService 声明了一个值类型的 MyService 变量,该结构体实例会被分配内存空间并初始化(其中包括 Name 字段),但在调用 PName() 方法时,会将 service 的一份拷贝传递给该方法,因此执行 PName() 方法会修改拷贝中的 Name 字段的值,但不会影响原来的 service 变量。
buffzty
328 天前
var service MyService
等于 var service = MyService{}
等于 service:= MyService{}
jiekeop
328 天前
谢谢各位解答,明白了
LeegoYih
328 天前
Go 反直觉的地方多了去了,学 Go 不能代入其他语言的思维。
无忌,你忘干净了吗?
lilei2023
328 天前
这个我刚学也比较懵
Cola98
328 天前
因为这是一个浅拷贝,第一个 name1 没有赋值,所以就给了默认值就是"",接着你 name2 为 zhangsan ,name3 会接着用之前的值

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/949872

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX