为什么在这个 Go 程序中指针会丢失其值?

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

Why the pointer is losing its value in this Go program

问题

我不明白为什么指针sinput()方法初始化后仍然是nil。有什么想法吗?

package main

import "fmt"


type ps string

func(s *ps)input(){
    x := ps("a")
    s = &x
}
func(s *ps)output(){
    
}

func main() {
    var v *ps
    v.input()
    if v == nil{
        fmt.Println("v shouldn't be nil")
    }
}

在这段代码中,input()方法接收一个指向ps类型的指针s。在方法内部,它创建了一个新的ps类型变量x,并将s指向x的地址。然而,这里的问题是,s是一个指针的副本,而不是原始指针本身。因此,对s的修改不会影响到原始指针v

要解决这个问题,你可以将input()方法修改为接收一个指向指针的指针,这样就可以修改原始指针的值。修改后的代码如下:

package main

import "fmt"


type ps string

func(s **ps)input(){
    x := ps("a")
    *s = &x
}
func(s *ps)output(){
    
}

func main() {
    var v *ps
    v.input()
    if v == nil{
        fmt.Println("v shouldn't be nil")
    }
}

现在,input()方法接收一个指向指针的指针s,并将s指向x的地址。这样,对s的修改将会影响到原始指针v,并且v将不再是nil

英文:

I don't understand why the pointer s is nil even after the input() method initialised it. Any idea?

package main

import "fmt"


type ps string

func(s *ps)input(){
	x := ps("a")
	s = &x
}
func(s *ps)output(){
	
}

func main() {
	var v *ps
	v.input()
	if v == nil{
		fmt.Println("v shouldn't be nil")
	}
}

Playground http://play.golang.org/p/jU2hoMP7TS

答案1

得分: 1

你需要两件事——main需要为input可以写入的ps分配空间,你可以通过将var v *ps替换为v := new(ps)来实现。字符串将是"",但它的内容并不重要,只要在内存中为input可以写入的string header分配了空间即可。正如Momer所说,否则指针将为nil,你的程序在尝试解引用时会发生恐慌。

为了通过指针赋值,input需要使用*s = x。由于*s在非正式场合下表示“获取s指向的内容”,你可以将其理解为“将s指向的内容更改为x”。通常,在点运算符和方法调用周围的自动引用/解引用行为会为你节省这个步骤,但是当你通过指针类型进行赋值或进行其他操作(如算术运算、索引等)时,代码中需要有解引用操作。

英文:

You need two things--main needs to allocate space for a ps that input can write into, which you can do by replacing var v *ps with v := new(ps). The string will be "", but it doesn't matter what it is, just that there's space set aside in memory for a string header that input can write to. As Momer said, otherwise the pointer's nil and your program panics trying to dereference it.

And in order to assign through a pointer, input needs to use *s = x. Since *s is, informally, "get what s points to", you can read that as "change what s points to to x". Usually the automatic ref/deref behavior around the dot operator and method calls saves you from that, but when you assign through a pointer type or do other operations (arithmetic, indexing, etc.) the dereference needs to be there in the code.

答案2

得分: 0

v值(0)被传递到v.input中。传递的值被存储在一个局部变量s中。s的值被修改。没有人将新的s值保存回v中。

如果你想在函数中修改某个值,你必须传递该值的指针(或者对于切片、映射等类型,传递引用)。

如果你想改变指针的值,你应该传递指向你的指针的指针。

Alex

英文:

v value (0) is passed into v.input. Passed value is stored in a local variable s. s value is modified. No one is saving new s value back into v.

If you want something modified in your function, you must pass pointer to the value. (or reference for slices, maps and so on).

If you want to change pointer value, you should pass pointer to your pointer.

Alex

huangapple
  • 本文由 发表于 2014年12月8日 08:45:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/27349731.html
匿名

发表评论

匿名网友

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

确定