This question already has answers here:
How to known a function of a interface is not realized? [duplicate]
(1 answer)
Go reflection with interface embedded in struct - how to detect "real" functions?
(5 answers)
Closed 2 years ago.
So, I was trying to find the solution via the search and web-search. Wasn't successful.
This has likely a simple solution, but probably I'm just a bit messed up.
I have prepared the following example in go playground.
// main.go
type myInterface interface {
Function1() string
Function2() int
}
type notMyStruct struct {
myInterface
// arbitrary implementation
}
func myFunc(val myInterface) {
fmt.Printf("%T %v", val, val)
fmt.Printf("this failes: %q", val.Function1())
// how to safely test,
// whether the underlying value
// has implemented the interface?
}
func main() {
myFunc(¬MyStruct{})
}
It consists of an interface myInterface, an arbitrary struct notMyStruct, which has the embedded interface (but not actually implemented) and some other arbitrary fields.
Now this struct is injected into myFunc, which the go compiler will accept, due to the fact that the interface is embedded.
But if myFunc tries to call a Function of the interface, it panics – understandably.
Assuming, I don't know the actual struct implementation (because I'm not in control of the interface-implementing code):
How can I reliably test, whether a given underlying value has an actual implementation of the method set (Function1 and Function2) defined by the interface?
I assume, this is solvable with reflect package (performance is not an issue here). Maybe there's any other solutions thinkable? Type assertion didn't seem to work out for me...
Related
This question already has answers here:
Go embedded struct call child method instead parent method
(1 answer)
Can embedded struct method have knowledge of parent/child?
(2 answers)
Ensuring embedded structs implement interface without introducing ambiguity
(2 answers)
What is the idiomatic way in Go to create a complex hierarchy of structs?
(1 answer)
Closed 8 months ago.
I have the following:
type A struct {
}
func (t *A) Do() {
print("A")
}
func (t *A) Display() {
t.Do()
}
type B struct {
A
}
func (t *B) Do() {
print("B")
}
And I will do like this
func TestC(t *testing.T) {
b := new(B)
// it will print "A", I neet it calling B's Do()
b.Display()
}
How to implement this, like java's abstruct class
It might be possible, but this isn't really how Go works. Go doesn't have classes, just structs, and structs can't be inherited, like classes can be. What you're doing here is embedding an A inside B. B then has:
b.Do
b.A.Display
b.A.Do
as it's "methods". There is no B.Display, so b.Do won't be called, because b.A.Display will be called instead.
There's not one specific way to do what you want as an alternative. You likely need to rethink how you would solve this problem. One possible solution is to define an interface, and then type your functions based on that interface. e.g.
type DoDisplay interface {
Do()
Display()
}
func IDo(obj DoDisplay) {
obj.Do()
}
func IDisplay(obj DoDisplay) {
obj.Display()
}
You would still need to define the Display method on B, and it very likely will still be the same as A. Other solutions might be to define a base type, and inject a specific do function to the struct (though I'd say that's a special case and not a recommended practice). Another solution might involve generics. There's also the ability to ask Go to generate code for you for these kinds of scenarios. But, the interface is likely the first thing you should try.
This question already has answers here:
Go reflection with interface embedded in struct - how to detect "real" functions?
(5 answers)
Closed 10 months ago.
I have a constructor that returns an interface. There are cases when that interface does not have actual implementation of some of its functions. Trying to call these unemplemented functions causes panic. I want to know is there a way to check is it safe to call a function or not, before actually calling it.
Here is the setup.
package main
type i interface {
Foo()
Bar()
}
type s struct {
i
}
func (r s) Foo() {}
func main() {
var ii i = &s{}
ii.Foo() // OK
ii.Bar() // will panic
}
The type s embeds an interface variable. Any call to interface methods not explicitly declared by s will panic because the embedded interface is nil. You should set that before calling the methods:
var ii i=&s{}
ii.i=<implementation of i>
So, it is not that the type s unimplemented methods. The type s delegates its method implementations to i, which is nil.
This question already has answers here:
Understanding polymorphism in Go
(2 answers)
Embedded types and polymorphism with structs
(2 answers)
Polymorphism in Go - does it exist?
(4 answers)
Multiple Struct switch?
(2 answers)
Closed 10 months ago.
I wish to use multiple structs which inherits from the same Base struct in a polymorphic manner.
Given those structs:
type Base struct { X bool }
type A struct {
Base // inherit Base
A bool
}
type B struct {
Base // inherit Base
B bool
}
I would like to pass either of those structs as an argument to a function polymorphically, and maybe read (or update) one of the Base struct fields:
func CheckIfX(base *Base) bool { // supposed to be a polymorphic function..
return base.X
}
b := &B{
Base{
X: true,
},
B: true,
}
CheckIfX(b) // fail with error..
What I have tried up until now:
Using interface{} and dynamic parsing within the function
(link to playground)
Make structs inherit from an interface
(link to playground).
Drawbacks:
No actual need of implementing methods on my use case, so feels like an overkill
Structs wont parse as expected (for example when trying to save on Firestore..)
I would also like to ask:
Lets say we couldn't come up with something better than dynamic parsing,
would you consider it a better practice than simply use 2 (or more) separet functions (rather than forcing it on a single one)?
This question already has answers here:
Type converting slices of interfaces
(9 answers)
slice of struct != slice of interface it implements?
(6 answers)
Passing a collection of interface types to a function
(1 answer)
Closed 3 years ago.
I'm trying to get better at using interfaces in Go to describe specific functionality, and using interface composition to write better, more understandable code. I ran into this problem which seems like it would be a common use case of go interfaces, yet I can't seem to figure out the proper syntax to use for this application. Here's some code to help explain what I am trying to do:
// Initializable is an interface to an object that can be initialized.
type Initializable interface {
Initialize() error
}
// InitializeAll initializes an array of members.
func InitializeAll(members []Initializable) error {
for _, member := range members {
err := member.Initialize()
if err != nil {
return err
}
}
return nil
}
// Host is an interface to an object providing a set of handlers for a web host.
type Host interface {
Initializable
Hostname() string
RegisterHandlers(router *mux.Router)
}
// ConfigureHosts configures a set of hosts and initializes them.
func ConfigureHosts(hosts []Host) (*mux.Router, error) {
err := InitializeAll(hosts) // compiler error here
}
This is the error: cannot use hosts (type []Host) as type []Initializable in argument InitializeAll.
My initial thought was that I was missing some sort of type downcast, which I know works for single interface objects, but had difficulty casting an array. When I tried doing err := InitializeAll(hosts.([]Initializable)), I got the following error: invalid type assertion: hosts.([]Initializable) (non-interface type []Host on left).
I'd appreciate any ideas as it comes to the design of this code example, and perhaps any suggestions as to proper syntax or some refactoring that I could do to solve this problem. Thanks!
I can't seem to figure out the proper syntax to use for this application
There is no such syntax. You simply cannot do this (directly).
This question already has answers here:
What is this "err.(*exec.ExitError)" thing in Go code? [duplicate]
(2 answers)
Closed 7 years ago.
Following is a snippet from one of the Go libs. Could anyone please point out the significance of r.(byteReader)? The syntax usage is not very obvious to a novice. byteReader is a defined interface and does not seem to be the member of io.Reader. Since, this seems to be some kind of nifty code, can anyone provide some insight.
The author mentions: "wrap it in a bufio.NewReader if it doesn't support ReadByte" pattern. https://github.com/dave-andersen/deltagolomb/blob/master/deltagolomb.go
type byteReader interface {
io.Reader
ReadByte() (c byte, err error)
}
func makeReader(r io.Reader) byteReader {
if rr, ok := r.(byteReader); ok {
return rr
}
return bufio.NewReader(r)
}
r.(byteReader) is called a type assertion. Even if io.Reader doesn't implement the byteReader interface in itself, it it still possible that the value stored in r might implement byteReader. So, by doing the type assertion, you can assert if that is the case:
The specification states:
x.(T) asserts that x is not nil and that the value stored in x is of
type T. The notation x.(T) is called a type assertion.
...
If T is
an interface type, x.(T) asserts that the dynamic type of x implements
the interface T.
Edit
The comment, "wrap it in a bufio.NewReader", refers to makeReader's provided io.Reader; if it doesn't implement byteReader, makeReader will wrap it in a bufio.Reader which does implement bytesReader, and return it instead.