通过公共getter提供对包级变量的访问 – 如何返回实例?

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

Providing Access to package level variable via public getter - How to return the instance?

问题

我有一个在应用程序启动时实例化的包级变量。尽管它被声明为包级变量,但我也需要从包外部访问它。为此,我有一个返回该变量的函数。

package app

var myService MyService

type MyService interface {
    DoThis()
    DoThat()
}

func Initialize() {
    
    // 初始化其他内容
    myService = initMyService()

}

func GetMyService() MyService {
    return myService
}

现在,在app包之外,当我需要对MyService进行操作时,我执行以下操作。

ms := app.GetMyService()
ms.DoThis()

这里有以下问题。

  1. 每次调用GetMyService()函数时,它不会返回myService的副本吗?
  2. 如果是这样的话,如果我在该函数中返回myService的指针,是否通过返回对最初实例化的单个myService实例的引用来解决这个问题?
英文:

I have a package level variable that I instantiate at the startup of the application. Even though it is declared to be package level, I need to access it from outside the package as well. To do that, I have a function that returns the variable.

package app

var myService MyService

type MyService interface {
    DoThis()
    DoThat()
}

func Initialize() {
    
    // initialise other stuff
    myService = initMyService()

}

func GetMyService() MyService {
    return myService
}

Now from outside of the app package, when I need to do something with MyService, I do following.

ms := app.GetMyService()
ms.DoThis()

Here I have following questions.

  1. Doesn't the GetMyService() function return copies of myService each time it is invoked?
  2. If that is the case, if I return a pointer to the myService inside that function, does it solve that problem by returning a reference to the single myService instance that was initially instantiated?

答案1

得分: 3

var myService MyService // 这里的 MyService 是一个接口。因此,你可以使用指针接收器方法或值接收器方法来实现它。

正如 Go 之旅tour.golang.org/methods/8中提到的

> 使用指针接收器有两个原因
>
> 第一个原因是方法可以修改其接收器指向的值
>
> 第二个原因是避免在每次方法调用时复制该值如果接收器是一个大型结构体这样做可能更高效...

如果你使用指针接收器方法来实现 MyService它将不会在每次调用时复制接收器

请参考 `golang.org/doc/faq` 中的 [Should I define methods on values or pointers?](https://golang.org/doc/faq#methods_on_values_or_pointers)。那里也有一个很好的解释。

示例实现如下

```go
type doer struct {
	// 任何字段
}

func (d *doer) DoThis() {
	// 任何实现
	fmt.Println(`do this`)
}

func (d *doer) DoThat() {
	// 任何实现
	fmt.Println(`do that`)
}

func initMyService() MyService {
	return &doer{
		// 初始化 doer 的字段
	}
}

<details>
<summary>英文:</summary>

`var myService MyService` here `MyService` is an `interface`. So you can implement it with pointer receiver methods or value receiver methods.

As go tour [tour.golang.org/methods/8][1] mentioned,

&gt; There are two reasons to use a pointer receiver.
&gt; 
&gt; The first is so that the method can modify the value that its receiver
&gt; points to.
&gt; 
&gt; The second is to avoid copying the value on each method call. This can
&gt; be more efficient if the receiver is a large struct...

If you implement `MyService` with pointer receiver methods, It will not copy the receiver in every call.

And please refer `golang.org/doc/faq` [Should I define methods on values or pointers?][2]. There is a good explanation for it too.

sample implementation like below

type doer struct {
// any fields
}

func (d *doer) DoThis() {
// any implementation
fmt.Println(do this)
}

func (d *doer) DoThat() {
// any implementation
fmt.Println(do that)
}

func initMyService() MyService{
return &doer{
// init doer fields
}
}



  [1]: https://tour.golang.org/methods/8
  [2]: https://golang.org/doc/faq#methods_on_values_or_pointers

</details>



huangapple
  • 本文由 发表于 2021年8月10日 19:26:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/68725961.html
匿名

发表评论

匿名网友

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

确定