英文:
Why do we need to use * to modify values of elementary datatypes but not of user defined structs?
问题
我是新手学习Go语言,对C语言有一些经验。现在最困惑我的是,在下面的代码中,为什么我们需要解引用str
来修改值,而不需要解引用chk.j
。
在结构体的情况下,这里发生了什么额外的事情?
type test struct {
i int
j string
}
func main() {
str := new(string)
*str = "Need Astrik"
chk := new(test)
chk.i = 5
chk.j = "Confused"
fmt.Println("printing", chk.i, chk.j, *str)
}
英文:
I am new to Go and have some experience in C. Now the thing which confuses me the most is why, in the code below, we need to dereference str
to modify value but not chk.j
.
What additional thing is happening in here in the case of structs?
type test struct {
i int
j string
}
func main() {
str := new(string)
*str = "Need Astrik"
chk := new(test)
chk.i = 5
chk.j = "Confused"
fmt.Println("printing", chk.i, chk.j, *str)
}
答案1
得分: 5
请参考规范中的选择器部分:
> 选择器会自动解引用指向结构体的指针。如果 x
是指向结构体的指针,x.y
是 (*x).y
的简写;如果字段 y
也是指向结构体的指针,x.y.z
是 (*(*x).y).z
的简写,依此类推。如果 x
包含一个类型为 *A
的匿名字段,其中 A
也是结构体类型,x.f
是 (*x.A).f
的简写。
总结一下:结构体的指针成员会自动解引用。
对于赋值操作,没有这样的快捷方式,因此赋值给指针的方式与 C 语言相同:
*p = value
对于具有指针成员 y
的结构体 x
,如果要将其目标赋值为一个值:
*x.y = value
如果 x
是指向结构体的指针,上述表达式可以转换为
*((*x).y) = value
英文:
See Selectors section in the spec:
> Selectors automatically dereference pointers to structs. If x
is a pointer to a struct, x.y
is shorthand for (*x).y
; if the field y
is also a pointer to a struct, x.y.z
is shorthand for (*(*x).y).z
, and so on. If x
contains an anonymous field of type *A
, where A
is also a struct type, x.f
is shorthand for (*x.A).f
.
In summary: pointer members of structs are dereferenced automatically.
For assignments there's no such shortcut, so assigning pointees is the same as in C:
*p = value
In the case of struct x
with a member y
that is a pointer you want to assign its target a value to:
*x.y = value
In case the x
is a pointer to a struct, the expression above translates to
*((*x).y) = value
答案2
得分: 1
new
创建一个指针。如果你想给指针指向的内容赋值,你需要对其进行解引用。如果你没有使用 new
创建值,你就不需要对指针进行解引用:
package main
import "fmt"
func main(){
var s string = "Hello World"
s = "hello"
var sp (*string) = &s
fmt.Println(s) //hello
fmt.Println(*sp) //hello
*sp = "world"
fmt.Println(s) //world
fmt.Println(*sp) //world
}
你不需要对 test chk
进行解引用,因为 .
在 Go 中可以根据你是在结构体上使用还是在指向结构体的指针上使用,而分别像 C 中的 ->
和 .
一样的行为。
英文:
new
creates a pointer. If you want to assign something to what the pointer is pointing to, you need to dereference it. If you didn't create your values with new, you wouldn't need to dereference any pointers:
//without magic := so you actually see the types of things
package main
import "fmt"
func main(){
var s string = "Hello World"
s = "hello"
var sp (*string) = &s
fmt.Println(s) //hello
fmt.Println(*sp) //hello
*sp = "world"
fmt.Println(s) //world
fmt.Println(*sp) //world
}
You don't need to dereference your test chk because .
can behave like both ->
and .
from C depending on whether you use it on a struct or a pointer to a struct.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论