I can create method alias for an usual method:
func method1() {
fmt.Println("method1")
}
var Method1 = method1
But cannot do the same for a method receiver:
type Person struct {
Name string
}
func (p *Person) methodReciver() {
fmt.Println("method reciver")
}
var MethodReciver = methodReciver
In this case I got the error on line var MethodReciver = methodReciver:
undefined: methodReciver
Full code:
package main
import (
"fmt"
)
type Person struct {
Name string
}
func method1() {
fmt.Println("method1")
}
var Method1 = method1
func (p *Person) methodReceiver() {
fmt.Println("method receiver")
}
var MethodReceiver = methodReceiver
func main() {
method1()
Method1()
p := Person{"Nick"}
p.methodReceiver()
p.MethodReceiver()
}
Playground
Is it possible to create a method alias for methodReceiver?
Basically you have 2 options:
1. Using a Method Expression
Which has the form of ReceiverType.MethodName and it yields a value of a function type:
var MethodReceiver = (*Person).methodReceiver
MethodReceiver just holds the function reference but not the receiver, so if you want to call it, you also have to pass a receiver (of type *Person) to it as its fist argument:
var p = &Person{"Alice"}
MethodReceiver(p) // Receiver is explicit: p
2. Using a Method Value
Which has the form of x.MethodName where the expression x has a static type T:
var p = &Person{"Bob"}
var MethodReceiver2 = p.methodReceiver
A method value also stores the receiver too, so when you call it, you don't have to pass a receiver to it:
MethodReceiver2() // Receiver is implicit: p
Complete Example
Try it on Go Playground.
type Person struct {
Name string
}
func (p *Person) printName() {
fmt.Println(p.Name)
}
var PrintName1 = (*Person).printName
func main() {
var p1 *Person = &Person{"Bob"}
PrintName1(p1) // Have to specify receiver explicitly: p1
p2 := &Person{"Alice"}
var PrintName2 = p2.printName // Method value, also stores p2
PrintName2() // Implicit receiver: p2
}
Output:
Bob
Alice
Yes. You can make an alias like this:
var MethodReceiver = (*Person).methodReceiver
When you call it, you have to provide a pointer to a person object as the first argument:
MethodReceiver(&p)
You can see this in action on the Go Playground.
This is called method expression var MethodReceiver = (*Person).methodReceiver
Playground
Related
I have a struct and the instance of that struct:
type Obj struct {
ssid string
code string
mit string
// and other props (23)
}
var ValidObject = Obj {
ssid: "AK93-KADJ9-92J76",
code: "SKO-120O"
mit: "MSLA-923-OKSW"
}
I want to create a slice of structs (Obj) which will contain ValidObject with only some fields changed. I think the best way to explain that would be using pseudo code, so here it is (using spread operator from JS :) ):
var slc = []Obj{
{
...ValidObject,
code: "Other value",
},
{
...ValidObject,
mit: "Other value"
}
}
Create a helper function that takes an Object, changes its code and returns the new Object:
func withCode(obj Obj, code string) Obj {
obj.code = code
return obj
}
Note that withCode takes a non-pointer value, so the Object you pass will not be modified, only the local copy.
And using this your task is:
var slc = []Obj{
withCode(ValidObject, "Other value"),
withCode(ValidObject, "Yet another value"),
}
fmt.Println(slc)
Output (try it on the Go Playground):
[{AK93-KADJ9-92J76 Other value MSLA-923-OKSW}
{AK93-KADJ9-92J76 Yet another value MSLA-923-OKSW}]
This helper withCode could even be a method (not a function).
Note that if you need to have variations of many fields, it would probably be better to add these as methods, so you can chain the calls.
For example:
func (o Obj) withCode(code string) Obj {
o.code = code
return o
}
func (o Obj) withSsid(ssid string) Obj {
o.ssid = ssid
return o
}
func (o Obj) withMit(mit string) Obj {
o.mit = mit
return o
}
And then using it:
var slc = []Obj{
ValidObject.withCode("code2").withSsid("ssid2"),
ValidObject.withMit("mit2").withSsid("ssid3"),
}
fmt.Println(slc)
Output (try it on the Go Playground):
[{ssid2 code2 MSLA-923-OKSW} {ssid3 SKO-120O mit2}]
Create a slice of struct var objCollector = []obj{} globally and read data into the defined struct and append the object into slice of struct that we created.
type Obj struct {
ssid string
code string
mit string
}
var objCollector = []obj{}
func main() {
var ValidObject = Obj{
ssid: "AK93-KADJ9-92J76",
code: "SKO-120O",
mit: "MSLA-923-OKSW",
}
append(objectCollector, ValidObject)
}
I would like to Mock the response of a function. But this function is located or called inside another function. Let say I have this function
// main.go
func TheFunction() int {
// Some code
val := ToMockResponse()
return val
}
func ToMockResponse() int {
return 123
}
Now on my test file
// main_test.go
func TestTheFunction(t *testing.T) {
mockInstance = new(randomMock)
mockInstance.On("ToMockResponse").Return(456)
returned := TheFunction()
assert.Equal(t, 456, returned)
}
As you can see within function TheFunction() a call to function ToMockResponse is made. Now I would like to test TheFunction but I would like to Mock the response of ToMockResponse how can I achieve this?
You should consider passing in the second function is as an parameter to the first.
You have a few options for doing that. You could simply pass it as a parameter.
func DoX(doY func()) {
doY()
}
That’s simple but doesn’t work well as the core get more complex. The better alternative is often to make the functions methods on a struct.
type X struct {
Y Y
}
type Y interface {
Do()
}
func (x *X) Do() {
x.Y.Do()
}
Then Y can be replaced with a mock.
Let's consider we have two functions, executor() and process() where executor function calls process function,
We need to write both the functions as shown below with structures and interfaces:
main.go is as shown below:
package main
import "fmt"
// A structure defined which will have a value of type processHandler(interface)
// This is helpful to pass a structure instance of processData later(see in main function)
// This is required to pass mock instance also
type processDataHandler struct{ procData processHandler }
// Interface defined for process method
type processHandler interface {
process() (int, string)
}
// structure on top of which executor method is getting called
type processData struct{}
// process method called by executor method
func (p processData) process() (int, string) {
return 23, "test2"
}
// executor method which has "processDataHandler" as argument
func (e processDataHandler) executor() (int, string) {
// Some code
//process function call
val, str_val := e.procData.process()
if val == 23 {
return 40, "success"
}
return 45, str_val
}
func main() {
procData := processData{}
dataHandle := processDataHandler{procData: procData}
val1, val2 := dataHandle.executor()
fmt.Println(val1)
fmt.Println(val2)
}
main_test.go is as shown below:
package main
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
//Define a mock insatnce
type processDataMock struct {
mock.Mock
}
func (m *processDataMock) process() (int, string) {
// this records that the method was called and passes in the value
// it was called with
args := m.Called()
// it then returns whatever we tell it to return
// in this case we are returing a integer type followed by a string type
return args.Int(0), args.String(1)
}
//Test function for executor method
func TestExecutor(t *testing.T) {
//define mock instance
procMock := new(processDataMock)
//Make process function to return 1 and "test" via mock
procMock.On("process").Return(1, "test")
//create a processDatahandler with mock instance
handler := processDataHandler{procData: procMock}
//call executor function which inturn mocks process via "procMock.On" above
a, b := handler.executor()
assert.Equal(t, 45, a)
assert.Equal(t, "test", b)
}
I have interface that requires its implementor to have Click method.
However, the type FakeTicker that implements this interface also implements Tick method in addition to Click method.
package main
type Ticker interface{
Click() string
}
type FakeTicker struct{
val string }
func (f FakeTicker) Click() string {
return f.val
}
func (f FakeTicker) Tick() int { return 1 }
func main() {
var clocker Ticker
clocker = FakeTicker{"Val"}
clocker.Tick()
}
Here I get the following error "clocker.Tick undefined (type Ticker has no field or method Tick)"
I understand that the interface only has method Click() but since FakeWriter is implementing the interface,
Shouldn't it be able to call its own method Tick()?
You would need to convert the interface{} to FakeTicker
package main
type Ticker interface {
Click() string
}
type FakeTicker struct {
val string
}
func (f FakeTicker) Click() string {
return f.val
}
func (f FakeTicker) Tick() int { return 1 }
func main() {
var clocker Ticker
clocker = FakeTicker{"Val"}
fakeTicker := clocker.(FakeTicker)
fakeTicker.Tick()
}
I understand that the interface only has method Click() but since FakeWriter is implementing the interface, Shouldn't it be able to call its own method Tick()?
Since your clocker variable is defined as the Ticker interface, you only have the methods defined on that interface. If you would like to access the Tick method, you will have to change to the FakeTicker type.
In this case, you can use type assertion.
func main() {
var clocker Ticker
clocker = FakeTicker{"Val"}
clocker.Click()
fake := clocker.(FakeTicker)
fake.Tick()
}
You should note that the type assertion will cause a panic when the assertion fails if you don't use the version with two return types (fake, ok := clocker.(FakeTicker)).
Look at my code here
package main
import (
"fmt"
)
type iFormatter interface {
SetName(name string)
Format() string
}
type BaseFormatter struct {
name string
}
type Formatter struct {
BaseFormatter
}
func (f Formatter) SetName(name string) {
f.name = name
}
func (f Formatter) Format() string {
return "formatted " + f.name
}
func main() {
var formatters = []iFormatter{Formatter{}}
formatters[0].SetName("KARL")
fmt.Println(formatters[0].Format())
}
I don't understand, why the field "name" is not setted after calling SetName.
Here is the link for playground https://play.golang.org/p/Jkcjv_hFRC.
The SetName() method should be on a pointer, not value. Currently the f is a copy of the formatters[0] and changes to f are not propagated to formatters[0].
The code below should do the trick.
func (f *Formatter) SetName(name string) {
f.name = name
}
...
var formatters = []iFormatter{&Formatter{}}
You don't need to change the Format() method to pointer receiver though in your case it could be better to do it.
See: https://play.golang.org/p/rFmCZesbTB
In your code, changing these two methods like this should make it work as you expect:
func (f *Formatter) SetName(name string) {
f.name = name
}
func (f *Formatter) Format() string {
return "formatted " + f.name
}
and using a pointer as
var formatters = []iFormatter{&Formatter{}}
https://play.golang.org/p/eSX3mXys-a
Basically, using a pointer receiver instead of a value receiver. Using a value receiver works on a copy of the struct instead of the original struct.
type FuncPtr func(int) int
func Foo(i int) { return i * i }
type Events struct {
SomeFunc FuncPtr
}
type Top struct {
events Events
}
func (self *Top) initEvents() {
// This change works within this function, but
// doesn't stick around after this method returns.
self.events.SomeFunc = Foo
}
func main() {
var t := Top{}
t.initEvents()
t.events.SomeFunc == nil // True: Change in initEvents() doesn't stick
}
How can I make the change inside initEvents() method persist? That is, I want to change the value of the function reference Top::Events::SomeFunc within the initEvents() method and for that change to stick once the initEvents() method returns.
The code you have works with some minor corrections to make it compileable.
There's no package declaration at the top
You're not specifying an integer return type for your function Foo
I've included a full example of the code below for convenience and if you want to run this yourself you can do it at: https://play.golang.org/p/Ngu8FFiGrI
package main
import(
"fmt"
)
type FuncPtr func(int) int
func Foo(i int) int {
return i*i
}
type Events struct {
SomeFunc FuncPtr
}
type Top struct {
events Events
}
func (self *Top) initEvents() {
// This change works within this function, but
// doesn't stick around after this method returns.
self.events.SomeFunc = Foo
}
func main() {
var t = Top{}
t.initEvents()
if t.events.SomeFunc == nil {
fmt.Println("SomeFunc not set")
}
fmt.Println("6^2 =",t.events.SomeFunc(6))
}