Why do we need to use * to modify values of elementary datatypes but not of user defined structs?

huangapple go评论88阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2014年4月7日 19:02:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/22910524.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定