I am an ex python dev sometimes struggling with the explicit nature of Go.
I am trying here to refactor some code in order to be able move a method from one structure to be part of an interface.
But the process seems weird to me, I wish to confirm I am not doing something incorrectly.
I have the following interfaces, structure and methods:
type Executing interface {
Execute()
}
type MyExecuter struct {
attribut1 string
}
//The function I wish to move
func (exe1 *MyExecuter) format() string {
return fmt.sprintf ("formated : %s", exe1.attribut1)
}
func (exe1 *MyExecuter) Execute() {
//Executing
fmt.Println(exe.format())
}
func GetExecuter () Executer{
return MyExecuter{attribut1: "test"}
}
So here I have a generic interface Execute, this interface will be accessed by the object returned by the GetExecuter method.
Now, as part of the implementation of one of my Executer, I want to move the Format method as part of an interface.
So I am doing the following:
type Formatting interface {
format() string
}
type Formatter struct {}
func (formatter *Formatter) format(exe1 *MyExecuter) (string) {
return fmt.sprintf ("formated : %s", exe1.attribut1)
}
So I create a new interface, a new empty structure, and update my function to take as attribute my previous structure.
While this seems to work, it seems to me this is a bit convoluted. Specially the part where I need to add a reference to my initial object as attribute of the method. Am I doing something wrong here, or this is the right way?
Your Executer implementation already implements the Formatting interface:
type Executing interface {
Execute()
}
type Formatting interface {
format() string
}
func (exe1 MyExecuter) format() string {
return fmt.sprintf ("formated : %s", exe1.attribut1)
}
func (exe1 MyExecuter) Execute() {
//Executing
fmt.Println(exe.format())
}
v:=MyExecuter{}
// Here, v implements Executing and Formatting interfaces
One thing to note here: Your code shows pointer receivers. That means the methods are defined for *MyExecuter, but not for MyExecuter. So you have to pass pointers to the struct instance for this to work. Or, as I did above, use the value receivers so the methods are defined for both MyExecuter and *MyExecuter.
Related
Trying to mock struct for testing. But following code has an error:
./test.go:32:17: cannot use NewClass() (type *Class) as type mockClass in return argument:
*Class does not implement mockClass (wrong type for Query method)
have Query() *Iterator
want Query() mockIterator
Why I can't do that?
func NewClass() *Class {
return &Class{}
}
type Class struct{}
func (Class) Query() *Iterator {
return &Iterator{}
}
type Iterator struct{}
func (Iterator) Next() error {
return nil
}
type mockClass interface {
Query() mockIterator
}
type mockIterator interface {
Next() error
}
var newMock = func() mockClass {
return NewClass()
}
In the test I want to assign to newMock something like:
newMock = funcr() mockClass {
return &fakeClass{}
}
The structs Class and Iterator are not under my control. Those structs come from external library.
Create an interface that expresses business logic that your component needs. Do not use any 3rd party types.
Use that interface in your business logic.
Create an implementation of this interface wrapping 3rd party library and pass it to your component in main.go, which is a good place to wire/inject various system components.
That way you can easily mock your interface and change the implementation for another if one day you decide not to use this 3rd party library.
If for some reason you are tied to this library and there is no way to create an interface not referencing 3rd party types, then have a look at the Can I mock out library code with a nested interface?
In following code snippet -
type Input interface {
Name() string
}
type Abc interface {
Do(Input)
}
type InputImpl struct {
}
func (InputImpl) Name() string {
return "sample-impl"
}
type AbcImpl struct {
}
func (abcImpl *AbcImpl) Do(input Input){
// do something
}
AbcImpl struct is an implementation of Abc interface, but changing last function like this -
func (abcImpl *AbcImpl) Do(input InputImpl){
// do something
}
Now the AbcImpl is not implementing Abc anymore, though InputImpl is implementing Input interface !
Am I missing something or it's compulsory to have exact same signature (not event Impls) as the interface to be a legitimate implementation?
Yes, you do have to follow the method signature you specified.
If you don't follow the signature, it will not be called "implementing".
an example: interface example
from tour of Go: There is no explicit declaration of intent, no "implements" keyword.
It is compulsory to use the very exact same signature when implementing an interface in Go. You can't implement it otherwise.
I have a package containing some structure and functions associated with it:
package samplepkg
type SampleStruct struct {
FirstString string
SecondString string
}
func init() {
// some operations
}
func CheckSomething(s *SampleStruct) bool {
// check something
}
Now I'm trying to run this function in another package:
import (
"MyProject/samplepkg"
)
func testFunc() {
var s = samplepkg.SampleStruct{"a", "b"}
if s.CheckSomething() {
// do some operations
}
}
But I get an error that s.CheckSomething is undefined. (&s).CheckSomething gives the same result. I can access s.FirstString and s.SecondString as well as use this method by calling
if samplepkg.CheckSomething(&s) {
// do some operations
}
But I feel it could be written in a better way. I'm aware that Go is not object-oriented language but is method invocation like this possible?
In Golang a Method set is defined as:
A type may have a method set associated with it. The method set of an
interface type is its interface. The method set of any other type T
consists of all methods declared with receiver type T. The method set
of the corresponding pointer type *T is the set of all methods
declared with receiver *T or T (that is, it also contains the method
set of T). Further rules apply to structs containing embedded fields,
as described in the section on struct types. Any other type has an
empty method set. In a method set, each method must have a unique
non-blank method name.
There is a mistake because you are using the pointer receiver with method when calling the function. So change the function when defining to method as:
func init() {
// some operations
}
func(s *SampleStruct) CheckSomething() bool {
// check something
}
Or when calling the method it should be function with argument SampleStruct which will be like
import (
"MyProject/samplepkg"
)
func testFunc() {
var s = &samplepkg.SampleStruct{"a", "b"}
if CheckSomething(s) {
// do some operations
}
}
Coming from OOP paradigms and porting a code from an OOP language, I come across a problem now which is solved in OOP via abstraction so I'm wondering how can I approach the following problem in Go which follows composition instead of inheritance.
In this scenario my ValueObjects (DTO, POJO etc.) are composed of other ValueObjects. I'm populating them through web service calls that returns json so basically my functions/method calls are common for all types and subtypes.
My super type EntityVO
type EntityVO struct {
EntityName string
EntityType string
PublicationId string
Version string
}
A subtype 1 composed with EntityVO
type ArticleVO struct {
EntityVO
ContentSize string
Created string
}
subtype 2 composed with EntityVO with it's own unique set of fields
type CollectionVO struct {
EntityVO
ProductId string
Position string
}
I'm calling web services to retrieve data and populate these VOs.
Earlier I had one function to call the web service and populate the data but now I'm duplicating the code for each VO.
type Article struct{}
func (a *Article) RequestList(articleVO *valueObject.ArticleVO) (*valueObject.ArticleVO, error) {
// some code
}
Duplicating the same code but changing the signature.
type Collection struct{}
func (c * Collection) RequestList(collectionVO *valueObject.CollectionVO) (*valueObject.ArticleVO, error) {
// some code - duplicate same as above except method signature
}
and I've several entities and just because my VO's are different I'm forced to duplicate the code and cater to each type of VO I've. In OOP sub types can be passed to a function accepting super types but not in go, so wondering how it should be done so I don't end up duplicated code that's different in signature only?
Any advice for a better approach in this kind of scenario?
This is where golang interfaces can shine.
It's worth noting, however, that it's difficult to write subclass/inheritance code in golang. We'd prefer thinking of it as composition.
type EntityVO interface {
GetName() string
SetName(string) error
GetType() string
...
}
type EntityVOImpl struct {
EntityName string
EntityType string
PublicationId string
Version string
}
func (e EntityVOImpl) GetName() string {
return e.EntityName
}
...
type ArticleVOImpl struct {
EntityVOImpl
ContentSize string
Created string
}
type CollectionVOImpl struct {
EntityVO
ProductId string
Position string
}
// CODE
func (e *Entity) RequestList(entityVO valueObject.EntityVO) (valueObject.EntityVO, error) {
// some code
}
In addition, as long as your interface files are shared, I don't think there should by any problem sending/marshalling/unmarshalling the structs over the wire.
The second parameter of json.Unmarshal is a "universal" interface{} type. I think similar approach is applicable to your case.
Define data type for storing web service properties which may differ for each entity, e.g.
type ServiceDescriptor struct {
URI string
//other field/properties...
}
Function for populating the entity may look like
func RequestList(desc *ServiceDescriptor, v interface{}) error {
//Retrieve json data from web service
//some code
return json.Unmarshal(data, v)
}
You can call the function to populate different type of entities, e.g.
desc := &ServiceDescriptor{}
article := ArticleVO{}
desc.URI = "article.uri"
//...
//You must pass pointer to entity for 2nd param
RequestList(desc, &article)
collection := CollectionVO{}
desc.URI = "collection.uri"
//...
//You must pass pointer to entity for 2nd param
RequestList(desc, &collection)
I have a couple of structures, like:
type SomeObject struct {
sample int
}
I want to fill the sample variable based on what I get in the request body. To do this, I want to create a function, pass request body as a string to it, create an empty structure inside, fill the structure with data, return it, and replace chosen structure with this.
How do I do this? What do I return from the function? Is there a way to do this?
If you're dealing with multiple types then you should make your method return an interface{}. For all of the applicable types, create a convenience method like;
func NewSomeObject(reqBody string) *SomeObject {
return &SomeObject{sample:reqBody}
}
Which takes a string and returns a new instance of the type with that field set to whatever was passed in. Your question is missing information about how you determine which type should be instantiated but assuming you have a few, you'll likely need an if/else or a switch in the method which receives the request body so to give a very vague example it would be something like;
func ProcessRequest(reqBody string) interface{} {
if someCondition {
return NewSomeObject(reqBody)
} else if otherCondition {
return NewSomeOtherObject(reqBody)
} // potentially several other statements like this
return nil // catch all, if no conditions match
}
How about
func foo (s *SomeObject) {
s.sample = 123
}
or
func (s *SomeObject) foo() {
s.sample = 123
}