package main
import (
"github.com/golang/mock/gomock"
"testing"
)
type Talker interface {
talk() string
}
type Person struct {
moth *Talker
}
func (p *Person) speak() string {
return (*p.moth).talk()
}
func TestPerson(t *testing.T) {
ctrl := gomock.NewController(t)
mockTalker := NewMockTalker(ctl)
person := Person{moth: mockTalker}
}
Assuming that I have already created a mock for Talker interface using mockgen.
I am getting error when I am creating Person{moth: mockTalker}. I am not able to pass mockTalker.
Don't user pointer interface. Essentially interface is pointer
type Person struct {
moth Talker
}
Normally, if function want return interface, it's will return new struct by pointer.
import "fmt"
type I interface {
M()
}
type S struct {
}
func (s *S) M() {
fmt.Println("M")
}
func NewI() I {
return &S{}
}
func main() {
i := NewI()
i.M()
}
In your Person struct the moth field is *Talker type. It is a pointer type of Talker interface. NewMockTalker(ctl) returns Talker type mock implementation.
You can do two things to fix this.
Change the Person's moth field's type to Talker.
type Person struct {
moth Talker
}
or
pass pointer reference of mockTalker to the person initialization`
person := Person{moth: &mockTalker}
Related
I have a basic handler, that uses an 3rd party package messager.
The package returns a concrete struct of messager.Shape provided by a Get method.
messager.go
type Shape struct {
Value struct {
Type string
Other int
Active bool
}
Markers struct {
Range int
Name string
}
ID string
}
...
func (m *Messager) Get(ID string) (Shape, error) {
...
}
handler.go
package handler
import (
"fmt"
"github.com/fake/message"
)
type Getter interface {
Get(ID string) (messager.Shape, error)
}
type Handler struct {
messager Getter
}
func NewHandler(g Getter) *Handler {
return &Handler{ messager: g }
}
func (h *Handler) DoSomething() {
fmt.Println(h.messager.Get("some-id").Value.Type)
}
The handler only really cares that something can provide a struct with a matching nested Value.Type string.
I attempted defining a struct for the interface that wanted just:
type ValueType struct {
Value struct {
Type string
}
}
type Getter interface {
Get(ID string) (ValueType, error)
}
but the compiler rejects it when creating a NewHandler as the messager.Get method type does not match the interface. What am I suppose to do here? Is it appropriate for my Handler to reference the package struct? Should the package not be returning something so definitive?
I appreciate the example is a bit contrived but just trying to work out what's correct.
I'm playing around with Golang and test cases in it, but it's almost completely different from other testing libraries in other languages (I'm with JS background)
In my file I have:
type MyHandler struct {
myBool bool
Person searchFile.Person
}
And lastly in my third file I have:
type Person interface {
searchFor(name string) (string, error)
}
In my main_test.go I have the following line:
h := &MyHandler{myBool: false} <- how can I mock the searchFor function in Golang
It's just an interface, so simply create a struct that implements the interface (and modify the interface so the method is exported, since it doesn't really make sense to have an unexported method in an interface):
type Person interface {
SearchFor(name string) (string, error)
}
type MockSearcher struct{}
func (m MockSearcher) SearchFor(name string) (string, error) {
return "mock name", nil
}
person := MockSearcher{}
h := &MyHandler{myBool: false, Person: person}
You can embed that interface !
package main
import (
"play.ground/sealed"
)
type sealedStruct struct {
sealed.Interface
}
func (s sealedStruct) sealed() {}
var j sealed.Interface = sealedStruct{}
func main() {
}
-- go.mod --
module play.ground
-- sealed/interface.go --
package sealed
type Interface interface {
sealed()
}
-- sealed/interface_test.go --
package sealed_test
import "test/d/sealed"
type sealedStruct struct {
sealed.Interface
}
func (s sealedStruct) sealed() {}
var j sealed.Interface = sealedStruct{}
https://play.golang.org/p/Ic_TnrLlF_u
Is there anyway that you can use the same function across multiple structs to satisfy an interface?
For example:
package main
import "fmt"
type Animal interface {
Speak() string
}
type Dog struct {}
func (d Dog) Speak() string {
return "Woof!"
}
type Wolf struct {}
func (w Wolf) Speak() string {
return "HOWWWWWWWWL"
}
type Beagle struct {}
func (b Beagle) Speak() string {
return "HOWWWWWWWWL"
}
type Cat struct {}
func (c Cat) Speak() string {
return "Meow"
}
func main() {
var a Animal
a = Wolf{}
fmt.Println(a.Speak())
}
Because Wolf and Beagle share the exact same function, is there anyway to write that function once, then share it between the two structs so that they both satisfy Animal?
You can create a parent struct that is embedded by each of the animals that "howl". The parent struct implements the Speak() string method, which means Wolf and Beagle implement the Animal interface.
package main
import "fmt"
type Animal interface {
Speak() string
}
type Howlers struct {
}
func (h Howlers) Speak() string {
return "HOWWWWWWWWL"
}
type Dog struct {}
func (d Dog) Speak() string {
return "Woof!"
}
type Wolf struct {
Howlers
}
type Beagle struct {
Howlers
}
type Cat struct {}
func (c Cat) Speak() string {
return "Meow"
}
func main() {
var a Animal
a = Wolf{}
fmt.Println(a.Speak())
}
https://play.golang.org/p/IMFnWdeweD
I am a new to golang. I need to design a function to create object of differing types based on input. But I failed to figure out how to design the interface. Here comes my code:
package main
import (
"fmt"
)
type AA struct{
name string
}
func (this *AA) say(){
fmt.Println("==========>AA")
}
type BB struct{
*AA
age int
}
func (this *BB) say(){
fmt.Println("==========>BB")
}
func ObjectFactory(type int) *AA {
if type ==1 {
return new(AA)
}else{
return new(BB)
}
}
func main() {
obj1 := ObjectFactory(0)
obj1.say()
obj2 := ObjectFactory(0)
obj2.say()
}
The compiler tells me error no matter I ask ObjectFactory return *AA or interface{}. How can I make it work?
First off, using type as a variable name is disallowed in go (see the spec). That is your first problem.
The return type of object factory is *AA. This means that it can only return variables of type *AA, which causes the return of type of BB to fail. As defined in the spec, go doesn't have type inheritance, just struct embedding.
If you create an interface called sayer, you can use that instead of *AA in your ObjectFactory function.
type sayer interface {
say()
}
You probably want to use this interface when trying to get multiple dispatch (as demonstrated in the code below (see on play.golang.org as well).
Try this code:
package main
import (
"fmt"
)
type sayer interface {
say()
}
type AA struct{
name string
}
func (this *AA) say(){
fmt.Println("==========>AA")
}
type BB struct{
*AA
age int
}
func (this *BB) say(){
fmt.Println("==========>BB")
}
func ObjectFactory(typeNum int) sayer {
if typeNum ==1 {
return new(AA)
}else{
return new(BB)
}
}
func main() {
obj1 := ObjectFactory(1)
obj1.say()
obj2 := ObjectFactory(0)
obj2.say()
}
I'm trying to add a pointer to a struct to a slice, but I can't get rid of this error:
cannot use NewDog() (type *Dog) as type *Animal in append:
*Animal is pointer to interface, not interface
How can I avoid this error? (while still using pointers)
package main
import "fmt"
type Animal interface {
Speak()
}
type Dog struct {
}
func (d *Dog) Speak() {
fmt.Println("Ruff!")
}
func NewDog() *Dog {
return &Dog{}
}
func main() {
pets := make([]*Animal, 2)
pets[0] = NewDog()
(*pets[0]).Speak()
}
package main
import "fmt"
type Animal interface {
Speak()
}
type Dog struct {
}
func (d *Dog) Speak() {
fmt.Println("Ruff!")
}
func NewDog() *Dog {
return &Dog{}
}
func main() {
pets := make([]Animal, 2)
pets[0] = NewDog()
pets[0].Speak()
}
You don't need a Slice of pointers to Animal interfaces.
http://golang.org/doc/effective_go.html#pointers_vs_values
just change your code to:
func main() {
pets := make([]Animal, 2)
pets[0] = NewDog()
pets[0].Speak()
}
a interface value is already an implicit pointer.