How can I invoke a variable method on a struct - go

I want to invoke a variable method on a struct like this example
type controller struct{}
func (c *controller) Index() {
fmt.Println("index controller")
}
func invokeIt(action string) {
(&controller{}).action // don't work duh
(&controller{})["action"] // this is Go not js
// how can I invoke it?
}
thx for the replies.

DHH, are you porting Rails to Go :) ?
Jokes aside, this is exactly what reflect is for. For example:
type Foo struct{}
func (Foo) FooM() { fmt.Println("Foom") }
func main() {
foo := Foo{}
reflect.ValueOf(foo).MethodByName("FooM").Call(nil)
}
Playground: http://play.golang.org/p/5ZGwlHLEmj
EDIT: A more idiomatic way to do it would be to use interfaces, (as someone else had proposed, but then have deleted their answer). So if you want to, say, define something that can do CRUD, in Go you'd usually go with
type Resources interface {
Index()
New()
Show(id int)
// ...
}
And maybe an Invoke method in order to invoke non-standard methods on this thing using reflect like above. reflect is very powerful and also a good way to shoot yourself in the foot, so it's never a good idea to overuse it.

Related

How to Mock inner methods in GoLang

e.g
type test struct { // few fields}
func (t *test) createresource(res1 string,res2 string)error {
//doing some task
t.createsubresource(res1)
}
func (t *test)createsubresource(res1 string)error{
//perform some task
}
I want to write test function for createresource , how can I mock t.createsubresource(res1) call. This is legacy code and I don't have permission to modify any above function.
Your mock can be done using interfaces, as for example:
main.go
package main
type TestInterface interface {
CreateResource(res1 string, res2 string) error
CreateSubresource (res1 string) error
}
func main() {
DoSomething(new(Test))
}
func DoSomething(t TestInterface) {
t.CreateResource()
}
main_test.go
package main
import "testing"
type TestMock struct {}
func (tm *TestMock) CreateResource(res1 string, res2 string) error {
return nil
}
func (tm *TestMock) CreateSubresource(res1 string) error {
return nil
}
func TestDoSomething(t *testing.T) {
err := DoSomething(new(TestMock))
//... do your assertions
}
Why does it works like that?
Calling a function that depends on a specific structure does not allow you to inject alternatives to it, that's why a solution using interface needs to be created. By having an interface, just implement a new structure that matches that interface and pass it as a dependency injection to the procedure that will be tested.
Also, check this out:
There is no easy way, by default, to just point your original structure and tell Go to make a mock from it. Maybe some 3rd party lib can do it (but I didn't saw that yet).
In go, public and private declarations are defined by the first letter as uppercase. By the lower cases declarations in your sample I've noticed that everything is private.
Usually it is not a good practice to test private methods. There are a lot of discussions about this topic, you can take a look in this one here
There are also some support libs to make assertions and mocks like for example stretchr/testify, please make a research first.
I hope that it helps you.

How can I (or should I) use Go interfaces for picking one of two packages? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
OK, I'm not quite getting it....
I have 2 modules I crafted with identical functions (in different files of course):
package mod1
func MyFunc() string {
return "mod1.Myfunc"
}
func Func2() string {
return "mod1.Func2"
}
package mod2
func MyFunc() string {
return "mod2.MyFunc"
}
func Func2() string {
return "mod2.Func2"
}
I have an interface defined correctly, (I think) in a third package:
package types
type MyType interface {
MyFunc() string
Func2() string
}
I have code which can pick whether I want to use mod1 or mod2, but I'm not quite understanding what I should have this code return:
func mypicker() ????{
}
Then in main, I want to somehow call either mod1.MyFunc() or mod2.MyFunc() based on
mypicker, without knowing which it is.... something like this:
func main() {
p := mypicker()
fmt.Print(p.MyFunc())
// and later
fmt.Print(p.Func2())
}
I read that interfaces are like void *, but clearly I'm not getting the complete picture.
Pointers to docs, code, anything useful would be great.
Interfaces should be used with types, not just plain functions. You can start by reading the Tour of Go sequence on interfaces. Here's an example close to your question's original code:
Given the interface:
type MyType interface {
MyFunc() string
Func2() string
}
You'd have a type:
type MyType1 struct{}
func (mt MyType1) MyFunc() string {
return "MyType1.MyFunc"
}
func (mt MyType1) Func2() string {
return "MyType1.Func2"
}
And similarly:
type MyType2 struct{}
func (mt MyType2) MyFunc() string {
return "MyType2.MyFunc"
}
func (mt MyType2) Func2() string {
return "MyType2.Func2"
}
And now, if you have some function that takes your MyType interface:
func Foo(m MyType) {
fmt.Println(m.Func2())
fmt.Println(m.MyFunc())
}
You could call it with either of your types that implements that interface:
m1 := MyType1{}
Foo(m1)
m2 := MyType2{}
Foo(m2)
Here's a Go Playground link where you can try this in action.
As for "picking a type", perhaps you mean something like this:
var mi MyType
if (... some condition ...) {
mi = m1
} else {
mi = m2
}
// Now you can do with mi whatever its interfaces permits,
// like calling mi.Func2(), etc.
Regarding the "picking one of two packages" part of the question:
Interfaces are implemented by types; they're orthogonal to packages and modules. In other words, an interface and types that implement it can all be in the same package, or in different packages, or in different modules.
You have to be careful with terminology. Go modules and Go packages are very different, even though both can be contained by directories. Basically, a directory is a package if it has at least one Go file in it and no go.mod file. If a directory has a go.mod file in it then it's recognized as a module. Generally, a whole project can be a single module with the go.mod file at the root of the project and that's sufficient. Assuming this is your case, move forward thinking that every sub-directory is just a package within that single module.
An interface doesn't really have to do with modules or packages, it has to do with types. The reason being is that an interface defines behavior, meaning it defines what methods are required for a type to accurately implement that interface. In your case, you defined both functions declared in your interface BUT they are NOT METHODS because they are top-level functions only attached to the package. In order for a function to be a method, it must be "attached" to a type. Then, that type becomes a valid implementation of that interface.
This...
package mod1
func MyFunc() string {
return "mod1.Myfunc"
}
func Func2() string {
return "mod1.Func2"
}
Needs to become this...
package mod1
type MyTypeImpl struct {}
func (m MyTypeImpl) MyFunc() string {
return "mod1.Myfunc"
}
func (m MyTypeImpl) Func2() string {
return "mod1.Func2"
}
The naming could be improved greatly but the point is that the above function declaration syntax is how you "attach" a function to a type, making it a method, which allows that MyTypeImpl struct to now be a valid implementation of your MyType interface.
Now you can call the interface methods without regards to which underlying type is actually the implementation:
var iType MyType
iType = MyTypeImpl{}
iType.MyFunc()
Notice that in that last line, it does not matter that we used MyTypeImpl to implement the interface. Once the implementation is assigned to a variable with the interface type, we just work with the interface and forget the underlying implementation. When we call iType.MyFunc(), Go will call the proper method from the underlying implementation.
If we had 100 different structs that implemented the MyType interface as MyTypeImpl does, they could all work for the right side of that iType = MyTypeImpl{} line. That's the point of an interface, to define it once and then use it without regard to what underlying struct is actually implementing it.

How do I improve the testability of go library methods

I'm writing some code that uses a library called Vault. In this library we have a Client. My code makes use of this Client but I want to be able to easily test the code that uses it. I use only a couple methods from the library so I ended up creating an interface:
type VaultClient interface {
Logical() *api.Logical
SetToken(v string)
NewLifetimeWatcher(i *api.LifetimeWatcherInput) (*api.LifetimeWatcher, error)
}
Now if my code is pointed at this interface everything is easily testable.. Except let's look at the Logical() method. It returns a struct here. My issue is that this Logical struct also has methods on it that allow you to Read, Write, ex:
func (c *Logical) Read(path string) (*Secret, error) {
return c.ReadWithData(path, nil)
}
and these are being used in my project as well to do something like:
{{ VaultClient defined above }}.Logical().Write("something", something)
Here is the issue. The Logical returned from the call to .Logical() has a .Write and .Read method that I can't reach to mock. I don't want all the logic within those methods to run in my tests.
Ideally I'd like to be able to do something similar to what I did above and create an interface for Logical as well. I'm relatively new to Golang, but I'm struggling with the best approach here. From what I can tell that's not possible. Embedding doesn't work like inheritance so it seems like I have to return a Logical. That leaves my code unable to be tested as simply as I would like because all the logic within a Logical's methods can't be mocked.
I'm sort of at a loss here. I have scoured Google for an answer to this but nobody ever talks about this scenario. They only go as far as I went with the initial interface for the client.
Is this a common scenario? Other libraries I've used don't return structs like Logical. Instead they typically just return a bland struct that holds data and has no methods.
package usecasevaultclient
// usecase.go
type VaultClient interface {
Logical() *api.Logical
SetToken(v string)
NewLifetimeWatcher(i *api.LifetimeWatcherInput) (*api.LifetimeWatcher, error)
}
type vaultClient struct {
repo RepoVaultClient
}
// create new injection
func NewVaultClient(repo RepoVaultClient) VaultClient {
return &vaultClient{repo}
}
func(u *vaultClient) Logical() *api.Logical {
// do your logic and call the repo of
u.repo.ReadData()
u.repo.WriteData()
}
func(u *vaultClient) SetToken(v string) {}
func(u *vaultClient) NewLifetimeWatcher(i *api.LifetimeWatcherInput) (*api.LifetimeWatcher, error)
// interfaces.go
type RepoVaultClient interface {
ReadData() error
WriteData() error
}
// repo_vaultclient_mock.go
import "github.com/stretchr/testify/mock"
type MockRepoVaultClient struct {
mock.Mock
}
func (m *MockRepoVaultClient) ReadData() error {
args := m.Called()
return args.Error(0)
}
func (m *MockRepoVaultClient) WriteData() error {
args := m.Called()
return args.Error(0)
}
// vaultClient_test.go
func TestLogicalShouldBeSuccess(t *testing.T) {
mockRepoVaultClient = &MockRepoVaultClient{}
useCase := NewVaultClient(mockRepoVaultClient)
mockRepoVaultClient.On("ReadData").Return(nil)
mockRepoVaultClient.On("WriteData").Return(nil)
// your logics gonna make this response as actual what u implemented
response := useCase.Logical()
assert.Equal(t, expected, response)
}
if you want to test the interface of Logical you need to mock the ReadData and WriteData , with testify/mock so u can defined the respond of return of those methods and you can compare it after you called the new injection of your interface

Explain go interface definition in go wiki

I understand a bit a go and to certain extend understand interface as well(like how I do ducktyping in ruby)
But reading the interface definition https://github.com/golang/go/wiki/CodeReviewComments
I'm clueless what is trying to convey.
1st: I did not understood the comment.
Go interfaces generally belong in the package that uses values of the interface type, not the package that implements those values.
2nd: I do not understand this
Do not define interfaces on the implementor side of an API "for mocking"; instead, design the API so that it can be tested using the public API of the real implementation.
3rd: I do not understand the example
Do not define interfaces before they are used: without a realistic example of usage, it is too difficult to see whether an interface is even necessary, let alone what methods it ought to contain.
package consumer // consumer.go
type Thinger interface { Thing() bool }
func Foo(t Thinger) string { ..... }
package consumer // consumer_test.go
type fakeThinger struct{ … }
func (t fakeThinger) Thing() bool { … }
if Foo(fakeThinger{…}) == "x" { ... }
// DO NOT DO IT!!!
package producer
type Thinger interface { Thing() bool }
type defaultThinger struct{ … }
func (t defaultThinger) Thing() bool { … }
func NewThinger() Thinger { return defaultThinger{ … } }
package producer
type Thinger struct{ … }
func (t Thinger) Thing() bool { … }
func NewThinger() Thinger { return Thinger{ … } }
Can someone explain in plain and easier word the 3 things above.
Forget analogies with other languages for the moment. Think of an interface like a contract - a set of requirements for the function that uses it.
Say I define a function MakeNoise which needs to know the sound of the thing passed in, but otherwise doesn't care about it. Code below is all together, but imagine this in two separate packages - one for concrete types and one for MakeNoise.
The MakeNoise function could take a specific type, but this limits it somewhat, might make testing harder etc, so often you might want it instead to define what it needs the type to do - in this case it just needs something with a Sound() method to call, other than that it doesn't care.
Now on the Cat/Dog side, you might not care about MakeNoise, or even know about it yet, your animals should be defined separately and not care about any interfaces they conform with - those interfaces might not even have been written yet.
So the Wiki is just saying that whoever writes MakeNoise should care about what it requires and put that in an interface, but whoever writes Cat/Dog should not care, and the interface should sit with MakeNoise, not with Cat/Dog. This means later someone might come and write a Giraffe in another package, and it can still be used with MakeNoise.
The interface is a requirement, not a promise.
https://play.golang.org/p/4r1wiXokKMb
// Here are some types which share one function.
// They might have other functions too
package main
type Cat struct {}
func (d Cat) Sound() string {
return "miao"
}
type Dog struct {}
func (d Dog) Sound() string {
return "woof"
}
func main() {
cat := Cat{}
dog := Dog{}
MakeNoise(cat)
MakeNoise(dog)
}
// Sounder is the requirement for MakeNoise, so it lives with it.
// perhaps in a package together which knows nothing of cats and dogs.
type Sounder interface {
Sound() string
}
// MakeNoise prints the sound of the thing
// it only cares the thing makes a Sound
func MakeNoise(thing Sounder) {
println(thing.Sound())
}

Composition combining data and functions with interfaces and structs

I'm wondering if this is something that's done in Go or if I'm thinking about it all wrong: composing type x interface and type x struct so my interface methods have access to specific data too:
The C programmer in my wants to do this:
type PluginHandler interface {
onLoad()
pm *PluginManager
}
func (ph PluginHandler) onLoad() {
pm.DoSomething()
}
There I have an interface defined with a function, but also some data I want to pass to those functions but this is a syntax error.
So is this something that's doable in Go through some other method or am I just thinking about the problem wrong?
You have defined onLoad incorrectly. You cannot define a function directly on interface type.
Once you have an interface, you need another type to implement methods specified in the interface. For example, if another type implements onLoad method, they automatically (implicitly) implement the interface PluginHandler.
The other thing you need to do is change the interface function type to accept the required data:
type PluginHandler interface {
onLoad(*PluginManager)
}
struct SomeType {
// ...
}
func (s SomeType) onLoad(pm *PluginManager) { // SomeType now implements
pm.DoSomething() // PluginHandler interface.
}
This way, you get to inject whichever PluginManager required by PluginHandler.
Also, you can use SomeType as a PluginHandler type whereever required.
func someFuntion(ph PluginHandler) {
// ...
ph.onLoad(pm)
// ...
}
Can be called with an input argument of type SomeType:
s := SomeType{}
someFunction(s)
TL;DR; There is no direct translation to Go.
Long answer:
Go interfaces are only methods.
Go structs are only data (with the possibility of receiver methods).
You can reference, and even embed interfaces within structs:
type Frobnicator interface {
Frobnicate() error
}
type Widget struct {
Frobnicator
WidgetName string
}
But that's not really what you're talking about.
The best answer to your dilema is, I believe: Take a step back. You're focusing on the trees, and you need to look at the forest. Go takes a different approach than C, or classical OO languages like C++ and Java.
Look at the general problem to be solved, and find solutions to that in Go. This can be a painful process (I can say from experience), but it's really the only way to learn the new way of thinking.
Just for the record, you can add extra methods to an existing type, by introducing another (indirection) type as:
type HandlerManager PluginManager
func (x *HandlerManager) onLoad() {
((*PluginManager)(x)).DoSomething()
}
And if you need to go with a more generic solution, a combination of Adapter & Strategy patterns could do:
type PluginHandlerAdapter struct{ _onLoad func() }
func (x *PluginHandlerAdapter) onLoad() {
x._onLoad()
}
Used like (public/private access ignored):
type PluginManager struct {
PluginHandlerAdapter
}
func NewPluginManager() *PluginManager {
res := new(PluginManager)
res._onLoad = res.DoSomething
return res
}

Resources