在结构体的方法中更改结构体指针的值。

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

change struct's pointer value in struct's method

问题

我正在努力理解Go语言中的指针。我有这段代码:

package main

import (
	"fmt"
)

// LinkedList 类型
type LinkedList struct {
	data int
	next *LinkedList
}

// InsertList 将一个项插入链表
func (node *LinkedList) InsertList(data int) {
	newHead := LinkedList{data, node}
	node = &newHead
}

func main() {
	node := &LinkedList{}
	node.InsertList(4)
	fmt.Printf("node = %+v\n", node)
}

输出结果是:

node = &{data:0 next:<nil>}

我想了解为什么node = &newHead,我的InsertList方法根本没有将节点指针引用到不同的结构体上。

英文:

I am trying to wrap my head around pointer in go. I have this code right here

package main

import (
	&quot;fmt&quot;
)

// LinkedList type
type LinkedList struct {
	data int
	next *LinkedList
}

// InsertList will insert a item into the list
func (node *LinkedList) InsertList(data int) {
	newHead := LinkedList{data, node}
	node = &amp;newHead
}

func main() {
	node := &amp;LinkedList{}
	node.InsertList(4)
	fmt.Printf(&quot;node = %+v\n&quot;, node)
}

and The output is

node = &amp;{data:0 next:&lt;nil&gt;}

I would like to understand that why is node = &amp;newHead my InsertList method did not reference the node pointer to a different struct at all

答案1

得分: 5

接收器 node 被按值传递,就像其他参数一样,所以在函数中所做的任何更改都不会被调用者看到。如果你希望函数修改函数外部存在的某个东西,函数需要处理指向该对象的指针。在你的情况下,node 是一个指针,但你真正想要的是指向表示链表本身的指针。例如:

package main

import (
	"fmt"
)

type LinkedListNode struct {
	data int
	next *LinkedListNode
}

type LinkedList struct {
	head *LinkedListNode
}

// InsertList 将一个项插入链表
func (list *LinkedList) InsertList(data int) {
	newHead := &LinkedListNode{data, list.head}
	list.head = newHead
}

func main() {
	var list LinkedList
	list.InsertList(4)
	fmt.Printf("node = %+v\n", list.head)
	list.InsertList(7)
	fmt.Printf("node = %+v\n", list.head)
}

希望这可以帮助到你!

英文:

The receiver node is passed by value just like other parameters, so any changes you make in the function are not seen by the caller. If you want a function to modify something that exists outside the function, the function needs to be dealing with a pointer to that object. In your case, node is a pointer, but what you really want is a pointer to something that represents the list itself. For example:

package main

import (
	&quot;fmt&quot;
)

type LinkedListNode struct {
	data int
	next *LinkedListNode
}

type LinkedList struct {
	head *LinkedListNode
}

// InsertList will insert a item into the list
func (list *LinkedList) InsertList(data int) {
	newHead := &amp;LinkedListNode{data, list.head}
	list.head = newHead
}

func main() {
	var list LinkedList
	list.InsertList(4)
	fmt.Printf(&quot;node = %+v\n&quot;, list.head)
	list.InsertList(7)
	fmt.Printf(&quot;node = %+v\n&quot;, list.head)
}

答案2

得分: 3

只需将值引用参数指向的位置更改为

func (node *LinkedList) InsertList(data int) {
	newHead := LinkedList{data, node}
	*node = newHead   // 在这里取消引用
}
英文:

Just change the value reference argument point to

func (node *LinkedList) InsertList(data int) {
	newHead := LinkedList{data, node}
	*node = newHead   //&lt;- dereference here 
}

答案3

得分: 2

想象一下:每个变量都必须存储在内存的某个位置上,你可以使用指针来存储该位置,而不仅仅是变量本身。

要使用指针获取或设置该位置上的值,你需要使用"间接"运算符。例如,*node将获取node指向的位置上的LinkedList*node = newHead将设置node指向的位置上的LinkedList

你还可以将指针指向新的内存位置,但该更改只在当前作用域中可见。在你的情况下,这意味着node = &newHead只会影响InsertList中的node指针,而不会影响main中的node指针。

这里有一个使用普通函数的简单示例,尽管方法也适用相同的规则:

// 修改`x`指向的值
func modifyValue(x *int) {
    fmt.Printf("  modifyValue: x=%3d @ %p\n", *x, x)
    *x = 1
    fmt.Printf("  modifyValue: x=%3d @ %p\n", *x, x)
}

// 修改指针`x`本身
func modifyPointer(x *int) {
    fmt.Printf("modifyPointer: x=%3d @ %p\n", *x, x)
    n := 1
    x = &n
    fmt.Printf("modifyPointer: x=%3d @ %p\n", *x, x)
}

func main() {
    x := 200
    fmt.Printf("         main: x=%3d @ %p\n\n", x, &x)
    modifyPointer(&x)
    fmt.Printf("         main: x=%3d @ %p\n\n", x, &x)
    modifyValue(&x)
    fmt.Printf("         main: x=%3d @ %p\n\n", x, &x)
}

输出结果:

         main: x=200 @ 0x1040e0f8

modifyPointer: x=200 @ 0x1040e0f8
modifyPointer: x=  1 @ 0x1040e134
         main: x=200 @ 0x1040e0f8

  modifyValue: x=200 @ 0x1040e0f8
  modifyValue: x=  1 @ 0x1040e0f8
         main: x=  1 @ 0x1040e0f8

Playground链接

英文:

Think of it like this: every variable must be stored at some location in memory, and you can use a pointer to store that location rather than just the variable itself.

To get or set the value at that location using the pointer, you need to use the "indirection" operator. For example, *node will get the LinkedList at the location that node points to, and *node = newHead will set the LinkedList at the location that node points to.

You can also point the pointer to a new memory location, but that change will only be visible in the current scope. In your case, that means node = &amp;newHead only affects the node pointer in InsertList, not the node pointer in main.

Here's a simpler example using normal functions, though the same rules apply for methods:

// Changes the value `x` points to
func modifyValue(x *int) {
	fmt.Printf(&quot;  modifyValue: x=%3d @ %p\n&quot;, *x, x)
	*x = 1
	fmt.Printf(&quot;  modifyValue: x=%3d @ %p\n&quot;, *x, x)
}

// Changes the pointer `x` itself
func modifyPointer(x *int) {
	fmt.Printf(&quot;modifyPointer: x=%3d @ %p\n&quot;, *x, x)
	n := 1
	x = &amp;n
	fmt.Printf(&quot;modifyPointer: x=%3d @ %p\n&quot;, *x, x)
}

func main() {
	x := 200
	fmt.Printf(&quot;         main: x=%3d @ %p\n\n&quot;, x, &amp;x)
	modifyPointer(&amp;x)
	fmt.Printf(&quot;         main: x=%3d @ %p\n\n&quot;, x, &amp;x)
	modifyValue(&amp;x)
	fmt.Printf(&quot;         main: x=%3d @ %p\n\n&quot;, x, &amp;x)
}

Output:

         main: x=200 @ 0x1040e0f8

modifyPointer: x=200 @ 0x1040e0f8
modifyPointer: x=  1 @ 0x1040e134
         main: x=200 @ 0x1040e0f8

  modifyValue: x=200 @ 0x1040e0f8
  modifyValue: x=  1 @ 0x1040e0f8
         main: x=  1 @ 0x1040e0f8

Playground link

huangapple
  • 本文由 发表于 2017年2月5日 10:15:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/42047889.html
匿名

发表评论

匿名网友

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

确定