首页 > 解决方案 > 如何通过 Go 中的指针接收器方法修改简单类型的值?

问题描述

我想有一个基于基本类型的自定义类型,并能够通过调用指针接收器来设置它的值。

当我运行以下程序时:

package main

import (
    "fmt"
    "strconv"
)

type FooInt int
func (fi *FooInt) FromString(i string) {
    num, _ := strconv.Atoi(i)
    tmp := FooInt(num)
    fi = &tmp
}

func main() {
    var fi *FooInt
    fi.FromString("5")
    fmt.Printf("%v\n", fi)
}

我收到<nil>。为什么声明的指针不将main()其值更改为的地址tmp

这是一个Go 游乐场链接

标签: pointersgo

解决方案


所有参数(包括接收者)都是函数/方法内部的副本。您只能修改副本。

这也适用于指针:接收器值(fi指针)是副本,因此您不能修改原始指针,只能修改副本。

通常接收者是一个非nil指针,而你修改了指向的值——这会导致原来的指向值改变。

在您的情况下,您要么必须返回指针并分配返回值:

func (fi *FooInt) FromString(i string) *FooInt {
    num, _ := strconv.Atoi(i)
    tmp := FooInt(num)
    return &tmp
}

func main() {
    var fi *FooInt
    fi = fi.FromString("5")
    fmt.Printf("%v %v\n", fi, *fi)
}

这将输出(在Go Playground上尝试):

0xc0000b4020 5

或者将非nil指针传递给您要更改的内容,在您的情况下,它将是类型**FooInt

func (fi *FooInt) FromString(i string, p **FooInt) {
    num, _ := strconv.Atoi(i)
    tmp := FooInt(num)
    *p = &tmp
}

func main() {
    var fi *FooInt
    fi.FromString("5", &fi)
    fmt.Printf("%v %v\n", fi, *fi)
}

这输出相同。在Go Playground上尝试一下。

但最简单的方法是确保接收器不是nil,因此可以简单地修改指向的值:

func (fi *FooInt) FromString(i string) {
    num, _ := strconv.Atoi(i)
    *fi = FooInt(num)
}

func main() {
    var fi *FooInt
    fi = new(FooInt)
    fi.FromString("5")
    fmt.Printf("%v %v\n", fi, *fi)
}

输出是一样的。在Go Playground上试试这个。


推荐阅读