golang interface that depends on interface - go

I am not sure if these should be two separate questions or one, but it seems to me as one question of two parts - How go interfaces are supposed to be used? I have this two struggles:
The methods of the interfaces are globally scoped: If I have interface A and interface B that both implement the same method Foo, but with different arguments or return types I am unable to implement both at the same time from the same type. For example, I have GetBytes() method in one interface having return type []byte and in another ([]byte, error) How I should overcome this issue?
Another issue I have is when I try to define interface say interface A that has a method that returns interface B that is defined in the same layer. Now if I want to create an object that implements A, if I return struct that implements B go is not smart enough to deduce that this method implements the method in A and it forces me to create dependency on B. This seems to completely defeat the point of the way interfaces work in go at first place. How can I avoid this issue?
for example, if I have:
type B interface {
Bar()
}
type A interface {
Foo() B
}
for the following structs :
type b_impl struct{}
func (b b_impl) Bar() {}
type a_impl struct{}
A foo method
func (a a_impl) Foo() b_impl {}
does not satisfy the interface A and I need to make it:
func (a a_impl) Foo() B {}
which makes a dependency to the package where B is declared.

1st question:
In go you need to make different function names, when you want to do different tasks. Let's look into the standard library at the strconv package how things are solved there: https://golang.org/pkg/strconv/#pkg-index
Look to the different declaration of the append function there. There are functions for every different type.
So if you expect a FooInt funtion your interface should be also a FooInter, ...
2nd question:As a small example. You don't need to import the whole io package, when you want to use the io.Writer interface. It is totaly ok to copy the Writer declaration into your own package. If you do that correct, every io.Writer implementation will automatically implement your own Writer interface.
After reading the other comments maybe you have a different situation:
Let's say there is a package a and b with the interface a.A and b.B. If there is the situation that:
type A interface{
Foo() b.B
}
and you have to write an implementation for a.A, then you need to import package b. But that makes your binaries not bigger, because you will always need to import package a, which depends on b.

For implementing an interface, you need to have exactly the same method name and signature. Means the signature must be with the same types.
As much as it seems weird, these two don't have the same signature:
Foo() B
Foo() b_impl {}
It doesn't matter that b_impl implements B.
To overcome the need to import the package B is declared in, you can use anonymous type. This way the compiler won't require a specific type for the method signature.
type A interface {
Foo() interface{Bar()}
}
Which also can be written as embedding B:
type A interface {
Foo() interface{B}
}
Still, a_impl must have same signature, so it also needs to return an anonymous interface. You can also declare the same B interface in the package of a_impl, and embed it in an anonymous interface.
package impl
type B interface {
Bar()
}
type b_impl struct{}
func (b b_impl) Bar() {}
type a_impl struct{}
func (a a_impl) Foo() interface{B} {
return b_impl{}
}
I don't know if it's a bad practice or not, probably there are cases which redesign is required instead of doing this.

Related

Create equivalent interface of another package with an interface as argument

I am practicing writing idiomatic Go code and discovered that interfaces should be declared in packages which are consuming them since they're implicit. However I came to this situation where by in the second package (package b) I want a function to call the receiver function of a struct in package a without coupling it tightly.
So naturally, I declare an interface in package b with the signature of the function I want to call from package a. The problem is that this function accepts an argument of a certain type which is an interface declared in package a. As I don't want package b to import package a, I defined an interface in package b with the exact same signature as the one which exists in package a. The playground link below shows the example code.
Playground
package main
import (
"fmt"
"log"
)
func main() {
manager := &Manager{}
coach := NewRunnerCoach(manager)
fmt.Println("Done")
}
// package a
type Runner interface {
Run()
}
type Manager struct {
}
func (o *Manager) RegisterRunner(runner Runner) {
log.Print("RegisterRunner")
}
func (o *Manager) Start() {
log.Print("Start")
}
// package b
type RunnerCoach struct {
runner *FastRunner
}
func NewRunnerCoach(registerer runnerRegisterer) *RunnerCoach {
runnerCoach := &RunnerCoach{&FastRunner{}}
registerer.RegisterRunner(runnerCoach.runner)
return runnerCoach
}
type FastRunner struct {
}
func (r *FastRunner) Run() {
log.Print("FastRunner Run")
}
// define ther registerer interface coach is accepting
type runnerRegisterer interface {
RegisterRunner(runner RunnerB)
}
// declaring a new interface with the same signature because we dont want to import package a
// and import Runner interface
type RunnerB interface {
Run()
}
This code does not compile. So the question here is that, am I using interface wrongly or should concrete types be defined in a separate package or lastly, is there a better code pattern for the problem I'm trying to solve?
EDIT: To clarify, package a and b does not import each other. The main() code exists in a separate package which connects these two.
IIUC, your question is not about packages but boils down to whether a function (or method)
can be typecast to another function which takes arguments with equivalent, but
not the same interface types.
Something like this: (Go Playground)
package main
type I1 interface{}
func f1(x I1) {}
func main() {
f := (func(interface{}))(f1)
f(nil)
}
Compilation error: ./g.go:8:26: cannot convert f1 (type func(I1)) to type func(interface {})
The answer appears to be no, because Go doesn't consider func (I1) to be
equivalent to func (interface{}). The Go spec says this
A function type denotes the set of all functions with the same parameter and result types.
The types func (I1) and func (interface{}) do not take the same parameters, even though
I1 is defined as interface{}. Your code fails to compile for a similar
reason because func (runner RunnerB) is not the same as func (runner Runner) and hence the method set of *Manager is not a superset of the
interface runnerRegisterer.
Coming to your original question:
I am practicing writing idiomatic Go code and discovered that interfaces
should be declared in packages which are consuming them since they're
implicit.
Yes, the idea is good but it doesn't apply to your implementation the way you
think it does. Since you're expecting to have different implementations of
runnerRegisterer and they must all have a method with the same signature
using the Runner interface, it makes sense to define Runner in a common
place. Also, as seen above Go wouldn't allow you to use a different interface
in the method signatures anyway.
Based on my understanding of what you're trying to achieve, here's how I think
you should re-arrange your code:
Define RunnerRegisterer (note: this is public) and Runner in one
package.
Implement your RunnerCoach in the same package and use the above
interfaces. Your RunnerCoach consumes types that implement the interfaces,
so it defines them.
Implement your runners in another package. You don't define the Runner
interface here.
Implement your Manager in another package, which uses the interface
Runner defined in RunnerCoach's package because it must take that type
as an argument if it wants to be used as a RunnerRegisterer.
The Solution
You've got a type that is used in two packages, A and B. Package A imports package B.
You have to avoid circular dependencies, so you have three choices:
Define the type in package B, so it will be available in both
packages.
Define the type in package C and have both A and B import package C.
Change your design such that the type is not used in both A and B.
These are your choices whether that type is an interface or any other type.
Choose the option that best fits your design goals.
The Rule / Idiom
I am practicing writing idiomatic Go code and discovered that
interfaces should be declared in packages which are consuming them
since they're implicit.
I get the impulse/idea - the problem is it's not very practical. Interfaces would be less useful if they could only be consumed in the package in which they are defined. The standard library is full of code that violates this axiom. Therefore I do not think the rule as presented -- applying to all interfaces in all situations, designs and contexts -- is idiomatic.
For example, look at the bytes package. func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) consumes io.Reader, an interface defined in another package. func (r *Reader) WriteTo(w io.Writer) (n int64, err error) consumes io.Writer, an interface defined in another package.

Visibility of embedded private interfaces in Go

If I embed an interface with a lowercase name (private) into another interface with an uppercase name (public), I assume that code outside of the defining package cannot see the embedded private interface. Is this assumption correct?
type b interface {
G() int
}
type A interface {
F() string
b
}
Code outside of the defining package cannot "see" the embedded b, correct? Outside code cannot call G through an instance of A.
Embedding unexported interface in interface
Interface embedding in interface is nothing more than merging the method set of the embedded interface into the embedder, so it becomes part of the method set of the embedder type. It doesn't matter if the embedded interface type is exported or not. Quoting from Spec: Interface types:
An interface T may use a (possibly qualified) interface type name E in place of a method specification. This is called embedding interface E in T; it adds all (exported and non-exported) methods of E to the interface T.
All that happens in your code is that A will be an interface with 2 methods: F() string and G() int. There won't be a "field" like A.b because A is an interface type, not a struct. So this isn't particularly "interesting".
How can you try it?
Create a folder subplay in any package, subplay.go:
package subplay
type b interface {
G() int
}
type A interface {
F() string
b
}
Create another go file that imports this subplay, e.g. play.go:
package main
import "play/subplay"
func main() {
var a subplay.A
a.G()
}
And it compiles. Runtime panic occurs though because a is not initialized (or rather left being nil), but if it would be, the a.G() call would not panic.
With the following additions there will be no run-time panic:
In subplay.go, add:
type aimpl struct{}
func (aimpl) F() string { return "aimpl.F() called" }
func (aimpl) G() int { return 1 }
func NewA() A {
return aimpl{}
}
And in play.go:
func main() {
var a subplay.A
a = subplay.NewA()
a.G()
}
The above code compiles and runs, and does not panic.
Also note that you can create a type in another package that implements subplay.A, you do not need to refer to subplay.b, because all that matters is the method set. The following another type also implements subplay.A, you can place this in play.go:
type another struct{}
func (another) F() string { return "aimpl.F() called" }
func (another) G() int { return 1 }
func main() {
var a subplay.A
a = another{}
a.G()
}
This again compiles and runs without run-time panic.
Embedding unexported interface in struct
A similar and more interesting case would be to embed an unexported struct (or an interface) type in a struct (and not in an interface), which "truly" creates an A.b field. Moreover, fields and methods of the embedded type get promoted to the embedder as if they would be fields or methods of the embedder. Quoting from Spec: Struct types:
A field or method f of an embedded field in a struct x is called promoted if x.f is a legal selector that denotes that field or method f.
Promoted fields act like ordinary fields of a struct except that they cannot be used as field names in composite literals of the struct.
Code outside of the defining package cannot refer to the embedded field A.b, this is correct, but code outside of the defining package can call the promoted A.G() method because this identifier is not lower-cased, so the restriction does not apply to it.
The restriction for non-exported identifiers is enforced by the compiler when you attempt to refer to them. Writing a.b.G() from another package is a compile-time error, because you are referring to a non-exported identifier (a.b). When you write a.G(), you are not referring to any non-exported identifiers, only to the exported a.G identifier, so it is allowed.

What's the purpose of ProtoMessage method?

when I generate go code from a protocol buffer file, I noticed that each of the generated structs implement the Message interface, https://github.com/golang/protobuf/blob/master/proto/lib.go#L277
For an example of the code that is generated, see https://github.com/google/go-genproto/blob/master/googleapis/rpc/status/status.pb.go#L97
Clearly, the other methods on Message interface, String() and Reset(), have an obvious purpose and the concrete implementation example makes that clear. However, I don't understand the purpose of the ProtoMessage() method. The method takes no parameters and returns no arguments, so why is it there?
Quoting from official doc: Protocol Buffers: Go Generated Code:
Given a simple message declaration:
message Foo {}
the protocol buffer compiler generates a struct called Foo. A *Foo implements the Message interface. See the inline comments for more information.
type Foo struct {
}
// Reset sets the proto's state to default values.
func (m *Foo) Reset() { *m = Foo{} }
// String returns a string representation of the proto.
func (m *Foo) String() string { return proto.CompactTextString(m) }
// ProtoMessage acts as a tag to make sure no one accidentally implements the
// proto.Message interface.
func (*Foo) ProtoMessage() {}
Note that all of these members are always present; the optimize_for option does not affect the output of the Go code generator.
This is a (similar) technique described in Go official FAQ: How can I guarantee my type satisfies an interface?
If you wish the users of an interface to explicitly declare that they implement it, you can add a method with a descriptive name to the interface's method set. For example:
type Fooer interface {
Foo()
ImplementsFooer()
}
A type must then implement the ImplementsFooer method to be a Fooer, clearly documenting the fact and announcing it in godoc's output.
type Bar struct{}
func (b Bar) ImplementsFooer() {}
func (b Bar) Foo() {}
Most code doesn't make use of such constraints, since they limit the utility of the interface idea. Sometimes, though, they're necessary to resolve ambiguities among similar interfaces.
So the ProtoMessage() method basically has 2 purposes:
The main purpose is as documented in the generated code: to make sure you don't pass a value for protobuf serialization / deserialization which otherwise (without this method) would implement the proto.Message interface but is not a "real" protobuf message value:
ProtoMessage acts as a tag to make sure no one accidentally implements the proto.Message interface.
And it also documents the fact that the type is a (implements) Message. This may not have a real value at first as the code is generated and you should not bother much with it, but code analyzers and Go IDE's may make good use of it; and it also appears in generated docs.

How to make this Go abstract type work?

package main
import "fmt"
type IA interface {
A()
B()
}
type AbsA struct {
IA
}
type CA struct {
AbsA
}
func (a CA) B() {
fmt.Println("Show B")
}
func (a AbsA) A() {
fmt.Println("Show A")
a.B()
}
func t7() {
var a IA
a = CA{}
a.A()
}
func main() {
t7()
}
Running this will get a nil pointer panic, because when AbsA calls B(), it will use the embedded IA, but IA is an interface.
Is there any way to make this work?
EDIT
I try to make a abstract super class, AbsA only implement part of interface, but it need to use other functions,A is a subclass of AbsA, only implement the rest part of interface.
But this looks bad, is there any other way to do this ? actually , I just want to do something like this
func (a IA)A(){
fmt.Println("Show A")
a.B()
}
but go can not use a interface as a receiver.
I don't know what you're trying to accomplish, but if you're defining structs with embedded interfaces, you need to initialize them.
http://play.golang.org/p/C32yWfNDRp
var a IA
a = CA{
AbsA: AbsA{
IA: CA{},
},
}
a.A()
If you're expecting OOP inheritance behavior, Go doesn't provide that. Embedding is only a form of automatic delegation.
No, at least not as you have it designed here. I'm not entirely sure what you're trying to accomplish but this is a very very poor use of embedding. The reason it doesn't work is because the CA type relies on the embedded AbsA type for method A() which then calls a 'method b' but the only actual implementation of B() has CA as the receiving type so once you've calling into the embedded types implementation of A() it can't call back up to the embedding types implementation of B().
You're treating embedding as if it's a two way street but in reality the embedding type knows all the methods on it's embed and the embed knows nothing about the embeddor. In my personal opinion, this should generate a compiler error. Perhaps in a future release it will (if I can tell at compile time that you will get a run-time error 100% of the time the compiler should able to too, right?).
As it is now you either need to implement B() with a receiver of type Absa or add another implementation of A() with a receiver of type CA. I'm not really sure what you're trying to accomplish so I can't say what the best course of action is. Note that if I were relating this to traditional OOP inheritance I would describe your code as attempting to access properties of a child class from within a parent class, clearly it's not possible. Absa will never be able to call up to an implementation of B() defined for the type embedding it. Just like trying to use a method defined on an inheriting type from the parent would never work or make sense only in most of the OOP languages you would get a compile time error.

How do I properly structure a package with sub packages in Go where a single type will be the receiver on most of the methods?

I'm currently in the design stage of writing a utility library that will make interaction with the x-go-binding a bit easier. (I've done this before with Python and xpyb.) For example, it will help with querying information defined in the EWMH spec and binding keys to callback functions. (And much more.) So as my initial idea for a package layout, consider:
xutil
ewmh
keybind
Where each is its own package. (Similar to how the standard library's image package is setup.)
What's unique about my situation is that almost every x-go-binding call requires some combination of an xgb connection object or a root window identifier. Therefore, it makes sense to me to store this information in a struct like so:
type XUtilConnection struct {
conn xgb.Conn
root xgb.Id
// a few other things, like a mapping of events to callbacks
}
So that I'd have a factory that could be used like so:
xconn = xutil.NewXUtilConnection(blah blah)
And it could be used like:
xconn.get_active_window()
xconn.bind_key("Shift-a", my_callback_fun)
There may also be functions like:
keybind.get_keycode("a")
ewmh.get_atom("_NET_ACTIVE_WINDOW")
My problem of course is that receivers, to my knowledge, can only be of types that have been declared in the same package. If I separate my packages, I cannot use my XUtilConnection type as a receiver in any of my sub-packages.
I suspect that my answer is going to be making this one big package separated into different logical files, but I fear that this might lead to namespace clutter. (For example, implementing the EWMH spec is probably on the order of 100+ functions.)
I am also aware that I could define a new container type in each sub-package for my XUtilConnection object. (I've heard that this should be a struct containing a single member XUtilConnection to avoid casting.) But this seems like a really messy situation to me, and would prevent the kind of semantics I'd like. (i.e., using an XUtilConnection struct to call methods in several different modules.)
I would suggest to use embedding.
In package xutil:
type XUtilConnection struct {
*ewmh.EWMH // Embed all methods of *ewmh.EWMH
*keybind.KeyBind // Embed all methods of *keybind.KeyBind
}
In package xutil/ewmh:
type EWMH struct {
Conn xgb.Conn
Root xgb.Id
// and any additional fields that are needed
}
// Some EWMH methods:
func (e *EWMH) GetAtom(name string) { ... }
func (e *EWMH) ...
In package xutil/keybind:
type KeyBind struct {
Conn xgb.Conn
Root xgb.Id
// and any additional fields that are needed
}
// Some keybind methods:
func (k *KeyBind) GetKeyCode(s string) { ... }
func (k *KeyBind) ...
This will enable you to directly call EWMH's and KeyBind's methods on values of type *XUtilConnection:
var c *XUtilConnection = ...
c.GetAtom("_NET_ACTIVE_WINDOW") // Call (*emwh.EWMH).GetAtom(string)
c.GetKeyCode("a") // Call (*keybind.KeyBind).GetKeyCode(string)
I'm not sure if I understood correctly the problem (I'm confused by seeing package names where they seem to be discussed as method receivers?), but I guess passing around an interface instead of the [*]struct would enable satisfying it from within any package. One can also always do something like (totally untested code):
package foo
type Foo interface { Bar(); Baz() }
----
package qux
import "foo"
type qux struct { foo.Foo; myStuff t }
func Foo(f foo.Foo) foo.Foo {
return qux{f, &t{}}
}
func (q qux) Bar() {
// smthg
}
To e.g. "override" f.Bar in package qux and "inherit" f.Baz() unaltered.

Resources