Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Pointers 为什么指针类型的行为与结构类型不同?_Pointers_Go_Struct - Fatal编程技术网

Pointers 为什么指针类型的行为与结构类型不同?

Pointers 为什么指针类型的行为与结构类型不同?,pointers,go,struct,Pointers,Go,Struct,我有一段Go代码,我试图分别使用两个函数f和f2来更改结构中常规int和int的值。我不明白为什么我需要做*I来更改int的值,但当我更改结构中X的值时,我不需要这样做 type Point struct { X int } func t(i *int) { *i = 20 } func t2(p *Point) { p.X = 200 } func main() { g := 30 t(&g) fmt.Println(g)

我有一段Go代码,我试图分别使用两个函数
f
f2
来更改结构中常规int和int的值。我不明白为什么我需要做
*I
来更改int的值,但当我更改结构中X的值时,我不需要这样做

type Point struct {
    X int
}

func t(i *int) {
    *i = 20
}

func t2(p *Point) {
    p.X = 200
}

func main() {
    g := 30
    t(&g)
    fmt.Println(g)

    p := Point{3}
    t2(&p)
    fmt.Println(p)
}

因为
i
*int
类型的指针,并且您想要修改所指向的对象,所以您必须编写
*i

同样的语法也适用于结构,例如,您可以编写
(*p).X
,但这是一个频繁的操作,因此规范允许使用
p.X
,这意味着
(*p).X
,没有歧义,并且是一个方便的快捷方式

它在里面

作为例外,如果
x
的类型是指针类型,并且
(*x).f
是表示字段(但不是方法)的有效选择器表达式,
x.f
(*x).f
的缩写


因为
i
*int
类型的指针,并且您想要修改所指向的对象,所以您必须编写
*i

同样的语法也适用于结构,例如,您可以编写
(*p).X
,但这是一个频繁的操作,因此规范允许使用
p.X
,这意味着
(*p).X
,没有歧义,并且是一个方便的快捷方式

它在里面

作为例外,如果
x
的类型是指针类型,并且
(*x).f
是表示字段(但不是方法)的有效选择器表达式,
x.f
(*x).f
的缩写


考虑这两个函数最简单的方法是在
t2
函数中,使用指向底层结构的指针更改结构的字段。在
t
函数中,您正在更改整个基础对象(int)

事实上,您可以编写
p.X
实际上只是一个小细节。在像C这样的语言中,如果操作的是非指针变量,则只能使用
p.X
。对于指针,您必须使用
p->X
表示您正在使用间接方式访问字段,或者确实取消对指针的引用(
(*p).X

在内部,go仍然做同样的事情,它只允许您省略显式解引用,并且它消除了对间接运算符的需要

然而,这两种功能并不等同<代码>点是一个结构,包含一个或多个字段。另一种类型是
*int
,int是单个标量值。要使
t2
等效(并重新分配整个基础对象),必须将代码更改为与
*int
情况下必须执行的操作相同:

func t2(p *Point) {
    *p = Point{
         X: 200,
         Y: p.Y,
     }
}

根据以下意见:TL;DR版本是指,如果访问结构类型的某个字段,则不必显式取消引用该类型的指针。您必须在C/C++中完成这项工作,但go编译器会为您解决这一问题。它表明您使用的变量是指针类型,并且编译
p.X
的方式与C编译器编译
p->X
的方式相同。因此,您不需要显式地取消引用
p

如果将
声明为:

type Point struct {
    X *int
}

因为表达式
p.X
的计算结果是
*int
类型的操作数,需要对其进行相应处理。

考虑这两个函数的最简单方法是在
t2
函数中,使用指向底层结构的指针更改结构的字段。在
t
函数中,您正在更改整个基础对象(int)

事实上,您可以编写
p.X
实际上只是一个小细节。在像C这样的语言中,如果操作的是非指针变量,则只能使用
p.X
。对于指针,您必须使用
p->X
表示您正在使用间接方式访问字段,或者确实取消对指针的引用(
(*p).X

在内部,go仍然做同样的事情,它只允许您省略显式解引用,并且它消除了对间接运算符的需要

然而,这两种功能并不等同<代码>点是一个结构,包含一个或多个字段。另一种类型是
*int
,int是单个标量值。要使
t2
等效(并重新分配整个基础对象),必须将代码更改为与
*int
情况下必须执行的操作相同:

func t2(p *Point) {
    *p = Point{
         X: 200,
         Y: p.Y,
     }
}

根据以下意见:TL;DR版本是指,如果访问结构类型的某个字段,则不必显式取消引用该类型的指针。您必须在C/C++中完成这项工作,但go编译器会为您解决这一问题。它表明您使用的变量是指针类型,并且编译
p.X
的方式与C编译器编译
p->X
的方式相同。因此,您不需要显式地取消引用
p

如果将
声明为:

type Point struct {
    X *int
}

因为表达式
p.X
的计算结果是
*int
类型的操作数,需要进行相应的处理。

所以
i
*int
类型的指针,
p
*Point
类型的指针。它们的行为不应该相同吗?@ninesat在修改指针值时,您应该始终首先编写
*p
。但是,给定一个指向结构的指针,修改指向的结构的字段是一个常见的操作,因此规范允许您使用快捷方式,即您可以省略指针间接指向,但它的含义是相同的。可读性,无歧义。因此,
i
*int
类型的指针,
p
*Point
类型的指针。他们不应该表现得一样吗?