How to implement two interfaces with same method name and different arguments - go

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.
}

Related

Assistance needed with struct concept in golang

I want to use slacknotificationprovider in the NewNotifier function. How can I do it. Also I want send a string(config.Cfg.SlackWebHookURL) in newNotifier function. What should I do? Also please suggest me some material to get a deeper knowledge of struct and interface in golang.
I also want to know why ProviderType.Slack is not defined as I have mentioned it in ProviderType struct as of SlackNotificationProvider type? Thanks.
type SlackNotificationProvider struct {
SlackWebHookURL string
PostPayload PostPayload
}
type ProviderType struct {
Slack SlackNotificationProvider
Discord DiscordNotificationProvider
}
type Notifier interface {
SendNotification() error
}
func NewNotifier(providerType ProviderType) Notifier {
if providerType == ProviderType.Slack {
return SlackNotificationProvider{
SlackWebHookURL: SlackWebHookURL,
}
} else if providerType == ProviderType.Discord {
return DiscordNotificationProvider{
DiscordWebHookURL: SlackWebHookURL + "/slack",
}
}
return nil
}
slackNotifier := NewNotifier(config.Cfg.SlackWebHookURL)
Errors:
1. cannot use config.Cfg.SlackWebHookURL (type string) as type ProviderType in argument to NewNotifiergo
2. ProviderType.Slack undefined (type ProviderType has no method Slack)go
Golang is a strongly typed language, which means the arguments to your functions are defined and can't be different. Strings are strings and only strings, structs are structs and only structs. Interfaces are golang's way of saying "This can be any struct that has method(s) with the following signatures". So you can't pass a string as a ProviderType and none of your structs actually implement the interface method you've defined, so nothing would work as you've laid it out. To reorganize what you've got into something that might work:
const (
discordType = "discord"
slackType = "slack"
)
// This means this will match any struct that defines a method of
// SendNotification that takes no arguments and returns an error
type Notifier interface {
SendNotification() error
}
type SlackNotificationProvider struct {
WebHookURL string
}
// Adding this method means that it now matches the Notifier interface
func (s *SlackNotificationProvider) SendNotification() error {
// Do the work for slack here
}
type DiscordNotificationProvider struct {
WebHookURL string
}
// Adding this method means that it now matches the Notifier interface
func (s *DiscordNotificationProvider) SendNotification() error {
// Do the work for discord here
}
func NewNotifier(uri, typ string) Notifier {
switch typ {
case slackType:
return SlackNotificationProvider{
WebHookURL: uri,
}
case discordType:
return DiscordNotificationProvider{
WebHookURL: uri + "/slack",
}
}
return nil
}
// you'll need some way to figure out what type this is
// could be a parser or something, or you could just pass it
uri := config.Cfg.SlackWebHookURL
typ := getTypeOfWebhook(uri)
slackNotifier := NewNotifier(uri, typ)
As far as documentation to help with this, the "Go By Example" stuff is good, and I see other people have already linked that. That said, a struct with one method feels like it should be a function, which you can also define as a type to allow you to pass back a few things. Example:
type Foo func(string) string
func printer(f Foo, s string) {
fmt.Println(f(s))
}
func fnUpper(s string) string {
return strings.ToUpper(s)
}
func fnLower(s string) string {
return strings.ToLower(s)
}
func main() {
printer(fnUpper, "foo")
printer(fnLower, "BAR")
}

Embedding of mutually dependent structures/interfaces

I have 3 structures that are similar about 70%. So I'd like to extract some common part and create some extensions with specific methods and fields.
Final structure will work as follows:
method .Start() from Common is called
Start() calls method .Name() from specific part the latter return a string
the returned result is being processed in (*Common).Process(), sometimes it should call specific's Format()
But! Specific part have to call Common part's method, for example GetVerbosity()
Like this:
package common
type Common struct {
Specificer
}
func (c *Common) Start() {
...
name := Specific.Name()
}
func (c *Common) GetVerbosity() {...}
type Specificer interface {
Name() string
Format() string
}
And specific part:
package specific1
// should implement common.Specificer interface
type Specific1 struct {
// unexported fields
}
func (s *Specific1) Name() string {...}
func (s *Specific1) Format() string {
// How to call it???
Common.Method()
}
This is similar to some frameworks - when another code calls your code, and also you call it's code.
How to implement this better? And how to create new structures?
I tried:
Embed Specific to Common, and embed vise versa:
type Common struct {
Specificer
}
type Specific1 struct {
common.Common
...
}
// But this is little bit insane:
func NewSpecific1() *common.Common {
var s = Specific1{}
return &common.Common{Specificer: &s}
}
Define 2 interfaces: Commoner and Specificer. And combined interface:
package common
type CommonSpecificer interface {
Commoner
Specificer
}
type Common struct {...} // implements all the methods from Commoner
func New() *Common {...}
//////
package specific1
type Specific1 struct { // implements all the methods from common.Specificer
Common
...
}
func NewSpecific1() *Specific1 {
c := common.NewCommon(...)
s := &Specific1{Common: c}
return s
}

Effectively wrapping public sdk types in golang

I am using pagerduty go sdk to do a bunch of api requests.
Particularly I am making use of
func NewClient(authToken string) *Client
to create a new Client type. I want to add some utility functions to my own work to *Client. I tried doing this:
type BetterPdClient *pagerduty.Client
func NewClient(auth string) BetterPdClient {
return pagerduty.NewClient(auth)
}
func (b *BetterPdClient) DoSomething() {
b.GetIncident(....)
}
func main() {
pd_client := NewClient("")
fmt.Println(pd_client)
pd_client.DoSomething()
}
But I get the following error:
invalid receiver type *BetterPdClient (BetterPdClient is a pointer type)
I understand that DoSomething() is expecting a pointer as caller. Only other way I could think of is sending the ptr as a function argument:
func NewClient(auth string) *pagerduty.Client {
return pagerduty.NewClient(auth)
}
func DoSomething(cl *pagerduty.Client) {
fmt.Println(cl)
}
func main() {
pd_client := NewClient("")
fmt.Println(pd_client)
DoSomething(pd_client)
}
Is there a better way?
Declaring a type as a pointer to another type is almost never what you want because Go doesn't allow you to add methods to that new type, nor to the pointer of that type as you've already figured out yourself. This one doesn't compile either:
type T struct{}
type P *T
func (P) M() {}
If you want to "extend" a type without "hiding" it's existing functionality your best bet is to embed it in a struct.
type T struct{
// ...
}
func (T) M() {}
type U struct {
*T
}
func NewU() *U {
return &U{&T{}}
}
func (U) N() {}
func main() {
u := NewU()
u.M()
u.N()
}
And what I mean by "hiding existing functionality" is that when you define a new type in terms of another, already existing type, your new type will not get direct access to the methods of the existing type. All you're doing is just saying that your new type should have the same structure as the already existing type. Although it's worth pointing out that this property gives you the ability to convert one type to the other...
type T struct{
// ...
}
func (T) M() {}
type U T
func NewU() *U {
return &U{}
}
func (U) N() {}
func main() {
u := NewU()
u.M() // compile error
u.N()
// convert *U to *T and then call M
(*T)(u).M()
}

Golang return child struct in place of parent like in c++

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.
}
}
}

how to get the method fields of a typed function (Go)

I'm wondering if it's possible to get the method fields from a typed function using reflection or by other means.
The problem that I'm trying to solve is that I have a method which accepts a function of specific type but I need to actually transport different types and based on the type provided to execute operations. I'm aware that I could use an interface{} value as receiver but I don't want to loose the type checking on the calling function ("GetIt")
package main
type ttp struct {
Coupons string
}
func (m ttp) GetIt(x string) {
if m.Coupons != "" {
print(m.Coupons)
}
}
func calculate(mth func(s string)){
//perform calculations and update the Coupon field
mth.Cupons = "one coupon" // is not working :(
// execute it again with the processed value
mth.GetIt() // is not working
}
func main() {
m := ttp{Coupons: "something"}
calculate(m.GetIt)
}
Play
well this does not answer your exact question but it should solve your problem and cleanup the logic: push the calculate method inside the type and use a interface
https://play.golang.org/p/On_AigRYW6
package main
import "fmt"
type Computer interface {
Compute(string)
}
type myp struct {
Coupons string
}
// myp implements Computer
func (m *myp) Compute(x string) {
m.GetIt(x)
fmt.Println("myp")
}
type ttp struct {
Various string
}
// ttp implements Computer
func (m *ttp) Compute(x string) {
m.GetIt(x)
fmt.Println("ttp")
}
func (m myp) GetIt(x string) {}
func (m ttp) GetIt(x string) {}
func main() {
m := &myp{Coupons: "something"}
t := &ttp{Various: "various stuff"}
var stuff = []Computer{m, t}
for _, c := range stuff {
c.Compute("s")
}
}

Resources