在函数内定义结构体的方法是:

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

Define method of struct inside function

问题

我有这段代码:

  1. func baz() {
  2. type mockDatabase struct{}
  3. //
  4. // 更多代码
  5. //
  6. }

我想定义一个mockDatabase的方法,所以完整的代码应该是这样的:

  1. func baz() {
  2. type mockDatabase struct{}
  3. func (m *mockDatabase) Foo() {
  4. // 在这里实现函数
  5. }
  6. //
  7. // 更多代码
  8. //
  9. }

我之所以这样做是因为我正在将一个依赖项注入到一个函数中,并且我想创建一个“模拟对象”来注入到该函数中(该函数以接口作为参数,模拟对象将实现该接口)。

我可以在外部创建结构体,但是在减少命名空间混乱方面,将结构体局部声明似乎更合理,特别是这些模拟对象只会被使用一次。我在这里有什么遗漏吗?将其定义在测试函数外部以避免代码过长是更好的做法吗?在这种情况下我应该怎么做?

英文:

I have this code

  1. func baz() {
  2. type mockDatabase struct{}
  3. //
  4. // More code
  5. //
  6. }

I want to define a method of mockDatabase, so the full code would look like this:

  1. func baz() {
  2. type mockDatabase struct{}
  3. func (m *mockDatabase) Foo() {
  4. // Implement function here
  5. }
  6. //
  7. // More code
  8. //
  9. }

The reason I want to do this is I'm injecting a dependency into a function, and I want to create a "mock object" to inject into the function (the function takes an interface as an argument and the mock object will implement the interface).

I could create the struct outside, but it seems more logical to declare the struct locally to decrease namespace clutter, especially when these mock objects will only be used once. Am I missing something here? Is it better practice to define it outside the test function so it's not long? What should I do here?

答案1

得分: 6

Go语言中的惯用方式是使用package进行命名空间管理。

  1. package mock
  2. type MockDatabase struct {}
  3. func (m *MockDatabase) Foo() {}

在主要的代码中,你可以从包中调用:

  1. package main
  2. import (
  3. "path/to/mock"
  4. )
  5. var m = mock.New(mock.MockDatabase)
  6. func baz() {
  7. m.Foo()
  8. }
英文:

The idiomatic Go would be to use package for namespacing.

  1. package mock
  2. type MockDatabase struct {}
  3. func (m *mockDatabase) Foo() {}

In the main code, you can call from the package

  1. package main
  2. import (
  3. "path/to/mock"
  4. )
  5. var m = New(mock.MockDatabase)
  6. func baz() {
  7. m.Foo()
  8. }

答案2

得分: 6

直接来说,不行。老实说,我认为pie-o-pah已经回答了你的问题。但是,如果你出于某种原因仍然想按照你的方式来做,你可以通过一些样板包装和巧妙地使用闭包来实现:

  1. type I interface {
  2. Foo()
  3. }
  4. type ExtendableI struct {
  5. foo func()
  6. }
  7. func (i ExtendableI) Foo() {
  8. i.foo()
  9. }
  10. func main() {
  11. type MyI int
  12. myI := MyI(42)
  13. foo := func() {
  14. fmt.Println(myI) // 闭包中引用myI,使其像一个方法一样工作。
  15. }
  16. ei := ExtendableI{foo: foo}
  17. useI(ei) // useI 需要一个 I。
  18. }

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

英文:

Directly - no. And honestly, I think that pie-o-pah answered your question. But. If you still want to do it your way for some reason, you can do it with a little bit of boilerplate wrapping and clever use of closures:

  1. type I interface {
  2. Foo()
  3. }
  4. type ExtendableI struct {
  5. foo func()
  6. }
  7. func (i ExtendableI) Foo() {
  8. i.foo()
  9. }
  10. func main() {
  11. type MyI int
  12. myI := MyI(42)
  13. foo := func() {
  14. fmt.Println(myI) // Close over myI making it work like a method.
  15. }
  16. ei := ExtendableI{foo: foo}
  17. useI(ei) // useI needs an I.
  18. }

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

huangapple
  • 本文由 发表于 2015年8月16日 06:55:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/32030169.html
匿名

发表评论

匿名网友

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

确定