Structural typing with Go
Whenever someone asks me what it is that sets [Go](http://golang.org) apart from most mainstream languages, it will inevitably be Go’s structual typing which earns confused looks. Today I stumbled upon an example by accident which I wanted to keep somewhere for future reference and to give to newcomers of the Go language. If you are fluent in Go, this will not be very interesting to you because you probably/hopefully have grasped the advantages of structural typing. ## Structural typing I was working with [Go’s image library](http://godoc.org/image) and to crop some images. An image in Go is nothing more than this tiny interface: type Image interface { ColorModel() color.Model Bounds() Rectangle At(x, y int) color.Color } Cropping images using only this interface is a somewhat tedious operation. It turns out, though, that almost all image types offer a [`SubImage()`](http://godoc.org/image#RGBA64.SubImage) method to do cropping. Calling this method is not only more convenient, but actually more efficient, because the image is not actually copied but just shares the underlying pixel buffer with its original. Why is `SubImage()` not part of the interface? Strictly speaking: Not being able to crop yourself does not disqualify you from being an image. It might not be possible for all types of images to do this kind of pixel-sharing. And if it doesn't, cropping can, ever-so agonizing, be generically implemented using the `Image` interface by copying pixel-by-pixel (an implementation is in fact provided by the `image/draw` package). This is the point where structural typing comes in. Instead of writing a huge switch-case to find the underlying image type and calling its `Subimage()` method, we define a new image interface type CropImage interface { image.Image SubImage(r image.Rectangle) image.Image } and just check, if the current image conforms to the `CropImage` interface func cropImage(r io.Reader) (image.Image, error) { img, _, err := image.Decode(r) if err != nil { return nil, err } if ci, ok := img.(CropImage); ok { return ci.SubImage(image.Rect(10, 10, img.Bounds().Max.X - 10, img.Bounds().Max.Y - 10)), nil } return nil, fmt.Errorf("Unable to crop image") } Without ever touching the definition of `image.Image` or the implementation of any specific image type, we have regrouped a subset of image types and effectively extended the interface so that all library functions keep working as expected. It is often said that Go has _duck_ typing. Structural typing, which is what Go actually has, is **not** the same. I quote Andrew Gerrand: > The difference is static typing. Duck typing, by definition, uses dynamic > dispatch. With structural typing it doesn't just look and sound like a duck > - it _is_ a duck. An important distinction. --- On a related note: Go supports `gif`, `png` and `jpeg` out of the box. What I didn’t know, that you don’t have to call the appropriate decoder directly yourself. Much more conveniently, just do a blank import of the image format packages and use the generic `image.Decode` function which detects what kind of image you got. import ( "image" _ "image/png" _ "image/jpeg" "io" ) func cropImage(r io.Reader) (image.Image, error) { // This will decode pngs and jpegs img, _, err := image.Decode(r) if err != nil { return nil, err } // ... }














