英文:
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()
这里有以下问题。
- 每次调用GetMyService()函数时,它不会返回myService的副本吗?
- 如果是这样的话,如果我在该函数中返回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.
- Doesn't the GetMyService() function return copies of myService each time it is invoked?
- 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,
> There are two reasons to use a pointer receiver.
>
> The first is so that the method can modify the value that its receiver
> points to.
>
> The second is to avoid copying the value on each method call. This can
> 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>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论