I have an application that has multiple concurrent implementations of the same API (e.g. one backed by a SQL database and another by a dataset stored in an XML file). What I'd really like to do is to define a parent type for each type of thing in the API that
holds the member variables that are common to all of the implementations and
defines the methods that all implementations must have.
So, in (invalid) Go, I want to do something like:
type Person interface {
Name string
Title string
Position string
Boss() *Person
}
type Person_XML struct {
Person
}
func (p *Person_XML) Boss() (*Person, error) {
// Poke around an XML document and answer the question
return boss, nil
}
type Person_SQL {
Person
}
func (p *Person_SQL) Boss() (*Person, error) {
// Do a DB query and construct the record for the boss
return boss, nil
}
But, of course, that's not legal since only structs have member variables and only interfaces have member functions. I could do this with just interfaces like this:
type Person interface {
Name() string
Title() string
Position() string
Boss() Person
}
type Person_XML struct {
NameValue string
TitleValue string
PositionValue string
Person
}
func (p *Person_XML) Name() string {
return p.NameValue
}
func (p *Person_XML) Title() string {
return p.TitleValue
}
func (p *Person_XML) Position() string {
return p.PositionValue
}
func (p *Person_XML) Boss() (Person, error) {
// Poke around an XML document and answer the question
return boss, nil
}
and similarly for other implementations. Is there an alternative that doesn't force me to turn member variables into member functions? What's best practice for such a use case?
Best practice would be to provide an interface:
type Person interface {
PersonName() string
PersonTitle() string
PersonPosition() string
Boss() (Person, error)
}
And also provide a struct which contains the common fields and the methods to get them:
type BasePerson struct {
Name string
Title string
Position string
}
func (p *BasePerson) PersonName() string { return p.Name }
func (p *BasePerson) PersonTitle() string { return p.Title }
func (p *BasePerson) PersonPosition() string { return p.Position }
(Note: *BasePerson itself does not implement Person as it doesn't have a Boss() method.)
Any type that embeds *BasePerson will automatically have its methods promoted, and so to implement Person, only the Boss() method will need to be added.
For example:
type PersonXML struct {
*BasePerson
}
func (p *PersonXML) Boss() (Person, error) {
// Poke around an XML document and answer the question
var boss *PersonXML
return boss, nil
}
*PersonXML does implement Person.
Example using it:
var p Person
p = &PersonXML{
BasePerson: &BasePerson{
Name: "Bob",
Title: "sysadmin",
Position: "leader",
},
}
fmt.Println(p.PersonName())
Output (try it on the Go Playground):
Bob
To create the PersonSQL type, you again only have to add the Boss() method if you embed *BasePerson:
type PersonSQL struct {
*BasePerson
}
func (p *PersonSQL) Boss() (Person, error) {
// Do a DB query and construct the record for the boss
var boss *PersonSQL
return boss, nil
}
*PersonSQL again does implement Person.
We can apply first approach since struct can embed interface along with fields. If you look at package sort It uses same approach in which it embeds an interface inside an struct.
type Interface interface {
// Len is the number of elements in the collection.
Len() int
// Less reports whether the element with
// index i should sort before the element with index j.
Less(i, j int) bool
// Swap swaps the elements with indexes i and j.
Swap(i, j int)
}
type reverse struct {
// This embedded Interface permits Reverse to use the methods of
// another Interface implementation.
Interface
}
So doing your approach is absolutely valid. And you can implement interface easily using struct receiver.
// Less returns the opposite of the embedded implementation's Less method.
func (r reverse) Less(i, j int) bool {
return r.Interface.Less(j, i)
}
Related
I have two different interfaces (from two different packages) that I want to implement. But they conflict, like this:
type InterfaceA interface {
Init()
}
type InterfaceB interface {
Init(name string)
}
type Implementer struct {} // Wants to implement A and B
func (i Implementer) Init() {}
func (i Implementer) Init(name string) {} // Compiler complains
It says "Method redeclared". How can one struct implement both interfaces?
As already answered, this is not possible since Golang does not (and probably will not) support method overloading.
Look at Golang FAQ:
Experience with other languages told us that having a variety of methods with the same name but different signatures was occasionally useful but that it could also be confusing and fragile in practice. Matching only by name and requiring consistency in the types was a major simplifying decision in Go's type system.
It is not possible.
In go you must have a single method signature.
You should rename one method.
The method signatures must match. If you want dependency injection I would recommend the functional option pattern. Functional options are functions that return other functions that are called in a loop in the constructor. Here is an example of how to use functional options and the basics of interfaces in go.
package main
import (
"fmt"
"strconv"
)
type SomeData struct {
data string
}
// SomeData and SomeOtherData both implement SomeInterface and SomeOtherInterface
// SomeInterface and SomeOtherInterface both implement each other.
type SomeInterface interface {
String() string
Set(data string)
}
func (s *SomeData)String() string {
return s.data
}
func (s *SomeData)Set(data string) {
s.data = data
}
// SetDataOption is a functional option that can be used to inject a constructor dep
func SetDataOption(data string) func(*SomeData) {
return func(s *SomeData) {
s.Set(data)
}
}
// NewSomeData is the constructor; it takes in 0 to many functional options and calls each one in a loop.
func NewSomeData(options ...func(s *SomeData)) SomeInterface {
s := new(SomeData)
for _, o := range options {
o(s)
}
return s
}
//********************
type SomeOtherData struct {
data string
i int
}
type SomeOtherInterface interface {
String() string
Set(data string)
}
func (s *SomeOtherData)String() string {
return s.data + " " + strconv.Itoa(s.i)
}
func (s *SomeOtherData)Set(data string) {
s.data = data
}
func SetOtherDataOption(data string) func(*SomeOtherData) {
return func(s *SomeOtherData) {
s.Set(data)
}
}
func SetOtherIntOption(i int) func(*SomeOtherData) {
return func(s *SomeOtherData) {
s.i = i
}
}
// NewSomeOther data works just like NewSomeData only in this case, there are more options to choose from
// you can use none or any of them.
func NewSomeOtherData(options ...func(s *SomeOtherData)) SomeOtherInterface {
s := new(SomeOtherData)
for _, o := range options {
o(s)
}
return s
}
//*********************************
// HandleData accepts an interface
// Regardless of which underlying struct is in the interface, this function will handle
// either by calling the methods on the underlying struct.
func HandleData(si SomeInterface) {
fmt.Println(si) // fmt.Println calls the String() method of your struct if it has one using the Stringer interface
}
func main() {
someData := NewSomeData(SetDataOption("Optional constructor dep"))
someOtherData := NewSomeOtherData(SetOtherDataOption("Other optional constructor dep"), SetOtherIntOption(42))
HandleData(someData) // calls SomeData.String()
HandleData(someOtherData) // calls SomeOtherData.String()
someOtherData = someData // assign the first interface to the second, this works because they both implement each other.
HandleData(someOtherData) // calls SomeData.String() because there is a SomeData in the someOtherData variable.
}
Assuming I got a type named State:
type State struct {
// ... does not matter what is inside
}
along with a method defined on it:
func (s *State) prettyName() string {
return "I am a state!"
}
Currently there is no way I can alter prettyName()'s behavior. I known that Go intentionally escapes OOP-like inheritance and methods overloading and this would probably never change, but still: what if I need prettyName() to behave differently depending upon whatever factor? The only solution I see is:
type State struct {
_prettyName func() string
}
func (s *State) prettyName() string {
return s._prettyName()
}
Is there a better Go-style way to achieve the same goal?
An interface should work here.
creating an interface like
type Stateful interface {
State() string
}
and a base state type
type BaseState struct{
}
func (s BaseState) State() string{
return "Base state"
}
you can imbed the BaseState struct
type MyStruct struct{
BaseState
}
so that State Will return "Base state", but can also implement its own method.
func (s MyStruct) State() string{
return "New State"
}
and now State will return "New State"
https://play.golang.org/p/QOajW0O6gIz
Instead of having prettyName as method on the struct, you can also define a member value of function type.
type State struct {
prettyName func() string
}
Then you can set its value to any function at runtime
a := State{}
a.prettyName = func() string {
return "I am a state!"
}
fmt.Println(a.prettyName())
a.prettyName = func() string {
return "another state"
}
fmt.Println(a.prettyName())
This example is on playground
Now you can define an interface type with PrettyName API and further algorithms/business logic will call PrettyName.
type StateAPI interface {
PrettyName () string
}
To fit your State type into the StateAPI interface, you need to define a trivial PrettyName method around the private function member
func (s *State) PrettyName() string {
return s.prettyName()
}
This is basically your original idea and it is totally legitimate. There is an example in the go programming language book by Alan A. A. Donovan and Brian W. Kernighan with exactly this construct.
That example sorts music record by different fields, e.g., by year, by artist, etc. In order to use the sort.Sort API,
func Sort(data Interface)
The input data needs to have three methods
type Interface interface {
// Len is the number of elements in the collection.
Len() int
// Less reports whether the element with
// index i should sort before the element with index j.
Less(i, j int) bool
// Swap swaps the elements with indexes i and j.
Swap(i, j int)
}
One way to sort by different fields is to define one custom data type for each case, say ByYear, ByArtist, etc. And define all three API methods for each case. But Len and Swap methods are redundant for all cases. A better solution is to define only one custom data type with a function member,
//!+customcode
type customSort struct {
t []*Track
less func(x, y *Track) bool
}
func (x customSort) Less(i, j int) bool {
return x.less(x.t[i], x.t[j]) }
func (x customSort) Len() int {
return len(x.t) }
func (x customSort) Swap(i, j int) {
x.t[i], x.t[j] = x.t[j], x.t[i] }
Then you can programmically control what less means.
The source code is here
I am trying to have a generic function that can return various multiple child objects. The idea is to be able to return those in a request json body.
The code is as follows
GenericType struct {
V1 string `json:"v1"`
V2 string `json:"v2"`
}
SubType struct {
GenericType
V3 string `json:"v3"`
}
func TestFunc() GenericType {
val := SubType{
GenericType: GenericType{
V1: "a",
V2: "b",
},
V3: "c",
}
return val
}
The error is
cannot use val (type SubType) as type GenericType in return argument
Is it possible to return a descendant struct in a parent pointer without losing the fields of that descendant struct and then return it as a JSON object in response body?
You can't use embedding as a substitute for inheritance. You could use interfaces for that though. Something like:
type Generic interface {
V1() string
V2() string
}
type parent struct {
// ...
}
type child struct {
// ...
}
// parent
func (p *parent) V1() string {
return "parent V1"
}
func (p *parent) V2() string {
return "parent V2"
}
// child
func (c *child) V1() string {
return "child V1"
}
func (c *child) V2() string {
return "child V2"
}
// further child methods
func NewGeneric() Generic {
return &parent{}
// or
// return &child{}
}
Go does not have inheritance (like C++ or Java), but only composition and interfaces. So your function could return only one type structure (or pointer) or interface. As a first approximation you could think that interface is nearly the same as pure abstract class in C++).
In your case interface is better. And now it depends how rest of the program will work with returned value. If it need to call a few methods (in go we prefer interface with only few method - ideal is one).
Eg.
type GenericType interface {
getV1() string
getV2() string
}
But unfortunately - for all object that could be serialized into JSON we don't have any common method (eg. int, string or arrays), therefore we have to use interface with no common method - interface{}.
Embedding
Embedding in Go doesn't allow to inherit (since it is not inheritance) attributes. When you are embedding one struct to another you are composing its' methods (not attributes) to a new composition.
Go does not provide the typical, type-driven notion of subclassing, but it does have the ability to “borrow” pieces of an implementation by embedding types within a struct or interface.
Interfaces
Go provides awesome interfaces to implement generic types and type assertion to have access to concrete types and its' attributes.
Plyground:
type generic interface {
say() string
}
type type1 struct {
msg string
}
func (t type1) say() string {
return t.msg
}
type type2 struct{}
func (t type2) say() string {
return "I'm type 2"
}
func main() {
t1 := type1{"Hey! I'm type1"}
t2 := type2{}
tl := []generic{t1, t2}
for _, i := range tl {
switch v := i.(type) {
case type1:
fmt.Println(v.say())
fmt.Println(v.msg)
case type2:
fmt.Println(v.say())
// fmt.Println(v.msg) Uncomment to see that type2 has no msg attribute.
}
}
}
Say I have two structs:
type First struct {
str string
}
type Second struct {
str string
}
And I want both of them to implement interface A:
type A interface {
PrintStr() //print First.str or Second.str
}
It seems redundant to have an implementation for both First and Second structs like so:
func (f First) PrintStr() {
fmt.Print(f.str)
}
func (s Second) PrintStr() {
fmt.Print(s.str)
}
Is there a way I can have one implementation for all the structs implementing interface A? Something like this, but it doesn't seem to work:
func (a A) PrintStr() {
fmt.Print(a.str)
}
Thank you!
No you can't, but you could create a base type and then embed it into your 2 struct, therefore only needing an implementation for the base type:
type WithString struct {
str string
}
type First struct {
WithString
}
type Second struct {
WithString
}
type A interface {
PrintStr() //print First.str or Second.str
}
func (w WithString) PrintStr() {
fmt.Print(w.str)
}
Usage:
a := First{
WithString: WithString{
str: "foo",
},
}
Complete Example on Playground
Embed documentation
If the printing logic depends on the interface but not on the structs themselves, then it is better to move printing to a free function that operates over an interface.
In your case, the PrintStr method is used to print a string which is a member of each structure.
In this case, it means that each structure should implement an interface that returns the necessary string used for printing, and PrintStr becomes a function taking a Printable parameter.
type First struct {
str string
}
type Second struct {
str string
}
type Printable interface {
String() string
}
func (p First) String() string {
return p.str
}
func (p Second) String() string {
return p.str
}
func PrintStr(p Printable) {
fmt.Print(p.String())
}
Your use of the A interface is non-idiomatic because an interface should not depend on the implementation of its functionality.
Instead, with this solution, you can still keep the A interface, but simplify each implementation:
func (f First) PrintStr() {
PrintStr(f)
}
func (s Second) PrintStr() {
PrintStr(s)
}
It is still redundant, but the logic lies in the function that is called from there, limiting the need to do copy-pasting in case of modification of the printing logic.
This pattern is common in the Go standard library, because many useful functions are built upon interfaces which they cannot extend, for example io.Reader.
It is a simple interface with only one method, but it is used thoroughly from many other packages.
If you look at the ioutil.ReadAll function, it could be argued that it could have been implemented as another method of the io.Reader interface, however this keeps readers simpler, concentrating on their single method, while allowing any implementor to use ReadAll for free.
Maybe not the best way to solve your problem, but you could use a wrapper in order to avoid "implementing" the function twice, something like this:
type First struct {
str StringWrapper
}
type Second struct {
str StringWrapper
}
type StringWrapper struct {
str string
}
func (f StringWrapper) PrintStr() {
fmt.Print(f.str)
}
func main() {
var a First = First{str:StringWrapper{str: "aaa"}};
a.str.PrintStr();
}
Why don't you just leave that function out of the interface and pass type A as a parameter?
type A interface {}
type First struct {
str string
}
type Second struct {
str string
}
func PrintStr(a A) {
fmt.Print(a.str)
}
I have heard a lot of people talk about Go, and how it does not support inheritance. Until actually using the language, I just went along with the crowd and listened to the hear say. After a little messing about with the language, getting to grips with the basics. I came across this scenario:
package main
type Thing struct {
Name string
Age int
}
type UglyPerson struct {
Person
WonkyTeeth bool
}
type Person struct {
Thing
}
type Cat struct {
Thing
}
func (this *Cat) SetAge(age int){
this.Thing.SetAge(age)
}
func (this *Cat GetAge(){
return this.Thing.GetAge() * 7
}
func (this *UglyPerson) GetWonkyTeeth() bool {
return this.WonkyTeeth
}
func (this *UglyPerson) SetWonkyTeeth(wonkyTeeth bool) {
this.WonkyTeeth = wonkyTeeth
}
func (this *Thing) GetAge() int {
return this.Age
}
func (this *Thing) GetName() string {
return this.Name
}
func (this *Thing) SetAge(age int) {
this.Age = age
}
func (this *Thing) SetName(name string) {
this.Name = name
}
now, what this does it composes the Person and Cat Structs, from the Thing Struct. By doing so, not only does the Person and Cat struct share the same Fields as the Thing Struct, but also, through composition, the methods of Thing are also shared. Is this not inheritance? Also by implenting an interface as such:
type thing interface {
GetName() string
SetName(name string)
SetAge(age int)
}
All three Structs are now joined or should I say, can be used in a homogenous fashion, such as an array of "thing".
So, I lay it on you, is this not inheritance?
Edit
Added a new derived Struct called "Ugly person" and Overridden the SetAge method for Cat.
It is inheritance but probably not the sort of inheritance you are probably after. Your example look promising b/c Person and Cat are behaviorally and structurally equal to each other modulo the type names.
As soon as you'd attempt to use this "inheritance" to 'extend' some base type with, for example added fields, you'll find that the receiver of the "base class" is always the base class, never the extended one. IOW, you cannot achieve structurally polymorphous type hierarchy.
OTOH, Go supports purely behavioral inheritance via interfaces. Embedding one interface into another does create an inheritance tree.
package main
import "fmt"
type Thing struct {
Name string
Age int
}
func (t *Thing) me() {
fmt.Printf("I am a %T.\n", t)
}
type Person struct {
Thing
}
func (p *Person) Iam() {
fmt.Printf("I am a %T.\n", p)
}
type Cat struct {
Thing
}
func (c *Cat) Iam() {
fmt.Printf("I am a %T.\n", c)
}
func main() {
var p Person
var c Cat
p.me()
p.Iam()
c.me()
c.Iam()
}
It's called composition. Methods of Person or Cat have no direct access to the fields of Thing. Also if e.g. Cat implements an own SetAge() and you want to call the one of Thing you would have to call myCat.Thing.SetAge(42) instead of myCat.SetAge(42).
Since you mentioned C#, try to do this in go. Method calls can't be made virtual in Go (except through interfaces).
// this is C#, not go
public class Thing
{
public virtual string Name {get; set;}
public virtual int Age {get; set;}
}
public class Person : Thing {}
public class Cat : Thing
{
public override int Age
{
get
{
return base.Age * 7; //age in cat's years
}
}
}
and call it like this:
Thing t = new Cat() {Name="Tom", Age=5}; // a Cat object is assigned
// to a Thing variable
Console.WriteLine(t.Age); // outputs 35.
// t.Age refers to Cat's implementation
// of Age, not Thing's. Notice how Age is virtual
// in Thing and overridden in Cat