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

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

Define method of struct inside function

问题

我有这段代码:

func baz() {
    type mockDatabase struct{}
    
    //
    //  更多代码
    //
}

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

func baz() {
    type mockDatabase struct{}
    
    func (m *mockDatabase) Foo() {
        // 在这里实现函数
    }
    
    //
    //  更多代码
    //
}

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

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

英文:

I have this code

func baz() {
    type mockDatabase struct{}
    
    //
    //  More code
    //
}

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

func baz() {
    type mockDatabase struct{}
    
    func (m *mockDatabase) Foo() {
        // Implement function here
    }
    
    //
    //  More code
    //
}

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进行命名空间管理。

package mock

type MockDatabase struct {}

func (m *MockDatabase) Foo() {}

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

package main

import (
        "path/to/mock"
)

var m = mock.New(mock.MockDatabase)

func baz() {
        m.Foo()
}
英文:

The idiomatic Go would be to use package for namespacing.

package mock 

type MockDatabase struct {}

func (m *mockDatabase) Foo() {}

In the main code, you can call from the package

package main

import (
        "path/to/mock"
)

var m = New(mock.MockDatabase)

func baz() {
        m.Foo()
}

答案2

得分: 6

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

type I interface {
    Foo()
}

type ExtendableI struct {
    foo func()
}

func (i ExtendableI) Foo() {
    i.foo()
}

func main() {
    type MyI int
    myI := MyI(42)
    foo := func() {
        fmt.Println(myI) // 闭包中引用myI,使其像一个方法一样工作。
    }
    ei := ExtendableI{foo: foo}
    useI(ei) // useI 需要一个 I。
}

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:

type I interface {
	Foo()
}

type ExtendableI struct {
	foo func()
}

func (i ExtendableI) Foo() {
	i.foo()
}

func main() {
	type MyI int
	myI := MyI(42)
	foo := func() {
		fmt.Println(myI) // Close over myI making it work like a method.
	}
	ei := ExtendableI{foo: foo}
	useI(ei) // useI needs an I.
}

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:

确定