如何在Go中设置单例状态?(或者,为什么这不起作用?)

如何在Go中设置单例状态?(或者,为什么这不起作用?),go,singleton,state,Go,Singleton,State,除非讨论是否应该使用单例(是的,我知道,反模式,反正我选择不使用它),否则我不明白为什么这不起作用。我有一个试图在单例实例中设置的状态,但我的方法实际上并没有修改主实例 当单例被实例化时,我传递的任何初始化都起作用 起初我认为这是一个嵌套结构问题,因为我从foo中的bar开始,但后来发现它对原语val做了同样的事情 我在Mac OS Mojave上运行Go 1.12.7,这很有可能是个问题 package main import ( "fmt" "sync" ) type f

除非讨论是否应该使用单例(是的,我知道,反模式,反正我选择不使用它),否则我不明白为什么这不起作用。我有一个试图在单例实例中设置的状态,但我的方法实际上并没有修改主实例

当单例被实例化时,我传递的任何初始化都起作用

起初我认为这是一个嵌套结构问题,因为我从
foo
中的
bar
开始,但后来发现它对原语
val
做了同样的事情

我在Mac OS Mojave上运行Go 1.12.7,这很有可能是个问题

package main

import (
    "fmt"
    "sync"
)

type foo struct {
    val   int
    state bar
}

type bar struct {
    inner int
}

var singleton *foo
var once sync.Once

func GetFoo() *foo {
    once.Do(func() {
        singleton = &foo{
            state: bar{inner: 0},
        }
    })
    return singleton
}

func (f foo) SetState() {
    f.val = 1
    f.state.inner = 1
}

func main() {

    f := GetFoo()
    fmt.Println(f)
    f.SetState()
    fmt.Println(f)

}
我预计这将产生:

&{0 {0}}
&{1 {1}}
相反,我得到的是:

&{0 {0}}
&{0 {0}}

塞里斯立刻发现了它。我没有意识到方法接收器在Go中本质上是按值传递的。因此,要修复此示例,只需将
SetState
签名更改为
(f*foo)SetState()

问题与单例无关。因为该方法有一个值接收者,所以当该方法返回时,对接收者参数所做的任何更改都将被丢弃。啊,那么接收者正在跟踪全局实例?接收者的行为如何/为什么/何时像值传递参数一样?所有参数,包括接收者,都是在Go中按值传递的。可能是复制品,是的,是的。如果可以的话,请签名,我没有做这件事的名声。