https://www.ccampo.me/go/2024/08/20/go-duck-typing.html Christopher J. Campo * About * Posts Duck Typing (horror) in Go by C. Campo August 20, 2024 in Go If you say Go supports "duck typing" online, you'll probably get some pushback. The Go community often points out that Go doesn't support duck typing because it's statically typed, and duck typing is a feature of dynamically typed languages. Rather, Go has "structural typing" where interfaces are still implicitly implemented, but still checked at compile time. From Wikipedia: Duck typing is similar to, but distinct from, structural typing. Structural typing is a static typing system that determines type compatibility and equivalence by a type's structure, whereas duck typing is dynamic and determines type compatibility by only that part of a type's structure that is accessed during runtime. ...and yet I can still write this horror show: package main import "fmt" type Duck interface { Swim() Quack() } type Mallard struct{} func (m Mallard) Swim() { fmt.Println("mallard swimming") } func (m Mallard) Quack() { fmt.Println("mallard quacking") } type Dog struct{} func (d Dog) Swim() { fmt.Println("dog swimming") } func (d Dog) Bark() { fmt.Println("woof") } func quack(ducks ...any) { for _, duck := range ducks { duck.(interface { Swim() }).Swim() duck.(interface { Quack() }).Quack() } } func main() { quack(Mallard{}, Dog{}) } Go ahead... run it! Go can duck type with the best of em! PS: please don't write real code like this. --------------------------------------------------------------------- Edit: since there appears to be some confusion, this is post is just having some fun! You should not write code like this. It's a bad idea. Don't do it. This example is intended to panic! The point is just to show that while it is often said that Go doesn't support duck typing, it clearly does when you use some of the more "dynamic" features of the language like any and type assertions and hack around the type system. It doesn't even require reflection, as one might expect, such as in Java^1, 2. It is essentially the Go analogue of the Wikipedia duck typing example in Python. There are very valid use cases for any and type assertions, but duck typing is not one of them! Of course, the "correct" implementation of the quack function would be to accept Duck instead of any and ditch the type assertion, which will result a compile time error: func quack(ducks ...Duck) { for _, duck := range ducks { duck.Swim() duck.Quack() } } func main() { // This will not compile. quack(Mallard{}, Dog{}) } See here for the error. If for whatever reason you were stuck with using any, you could still use the two-valued type assertion (or a type switch) to check if the type implements Duck, which of course is still a runtime check, but at least it avoids the panic: func quack(ducks ...any) { for _, duck := range ducks { if d, ok := duck.(Duck); ok { d.Swim() d.Quack() } else { fmt.Println("not a duck") } } } See here for the output. Still, prefer using the type system and the compiler to your advantage whenever possible! Thanks for reading! Subscribe via RSS Share: Please enable JavaScript to view the comments powered by Disqus. comments powered by Disqus Christopher J. Campo Site Map * About * Posts Contact * chris@ccampo.me * campo133 * ccampo133 * LinkedIn * ccampo Subscribe via RSS I'm Chris Campo, and these are some things I find interesting.