16 ms·
Indent 4 spaces for code. Here's another way to do this in Go: func f(obj interface{}) { switch obj := obj.(type) { case Foo:
by brandonbloom 10y ago
Indent 4 spaces for code.
Here's another way to do this in Go:
func f(obj interface{}) {
switch obj := obj.(type) {
case Foo:
// Do stuff with obj.x
case Bar:
// Do stuff with obj.y
default:
return fmt.Errorf("obj is of unexpected type: %T", obj)
}
}
- i_don_t_know 10y agoThanks for the formatting help!
- weberc2 10y agoUnfortunately, this makes a runtime error from something that could be caught at compile time.
- adrusi 10y agoIt's possible to make closed interfaces in Go (give it an uncapitalized method), so there could be a compile-time warning when you don't handle all possible cases in a type switch on a closed interface.
- weberc2 10y agoMaybe this is possible (and I'm not sure it is--this seems like the sort of thing struct embedding would break), but it still doesn't fix that interfaces incur an alloc. Further, it's a shame to abuse interfaces like this; it's not very ergonomic to define a method on a type to denote its membership in a set when we could do something like `type Foo enum { int, Bar, string, []byte }`. None of this is to say implementing real enums in the language is an easy endeavor; only that interfaces are a poor substitute.
- jerf 10y agoIt is possible, and struct embedding does not break it because struct embedding only enables composition. There is no inheritance, so you can not embed a struct that has something private in it and then "inherit" it and override the private stuff. There is no such thing as inheritance in Go. You can "decorate" methods (in the GoF patterns sense), but the internal implementation that you are decorating only gets the instance of itself, not the decorating class. I'm not addressing your other points, just your first sentence, since that is a matter of fact I can concretely address.
- weberc2 10y ago> struct embedding only enables composition Not sure what you mean here. Struct embedding is composition. It enables delegation of methods, which allows the outer struct to satisfy the same interfaces as the inner struct. This necessarily means you can't create closed interfaces. See for yourself: https://play.golang.org/p/akn9rir5of https://play.golang.org/p/akn9rir5of This holds even if the outer and inner structs are defined in different packages.
- deleted 10y ago[deleted]
- jerf 10y agoThis actually sent me down quite the path of discovery, which yielded to me a couple of surprises which I may have to document somewhere else. But the answer to your question is that you can seal an interface by declaring a private interface that has a private method. If you do that, nobody can construct any type that will implement that, even if they peek in the module and look at the private method name. The compiler will yield up something like: src/b/b.go:16: cannot use b (type B) as type a.private in argument to a.CallPrivate: B does not implement a.private (missing a.privatemethod method) have privatemethod() want a.privatemethod() A public interface with a private method does behave a bit interestingly. You can create new structs that compose in the implementation, and if you have a function (not method, function) in the private package that tries to type match on them, it can indeed end up with a type unknown to your package. However, you still have not necessarily "opened the interface" because it remains impossible to ever call a private method on that interface that was not defined in the original package. I haven't tested what public methods do. I was able to construct a struct that in some sense had two different methods which could both be called under different circumstances with the same short method name, which is a bit weird. So, in Go, you can completely close an interface such that you'll never get a type you don't expect, or you can close an interface in a way that means you may get an underlying type you didn't expect but the method will still be guaranteed to come from your package.