== Go: using type assertions to safely reach through interface types To start with, suppose that you have a [[Go http://golang.org/]] _net.Conn_ value, call it _conn_, that you want to _shutdown()_ (for writing) on if possible. Some but not all specific concrete _net_ connection types make this available as a _.CloseWrite()_ method (eg it's available for TCP sockets but not for UDP ones), but _net.Conn_ is an interface type and it doesn't include a _.CloseWrite()_ method so you can't directly call _conn.CloseWrite()_. (In Go's software engineering view of the world this is a sensible choice. _net.Conn_ is the set of interfaces that *all* connections can support. If you included _.CloseWrite()_ in the interface anyways you would force some connections, eg UDP sockets, to implement a do-nothing or always-error version of the method and then people would write Go code that blindly called _.CloseWrite()_ and expected it to always work.) So sometimes _conn_ will be of a concrete type that supports this (and sometimes it won't be). You want to somehow call _.CloseWrite()_ if it's supported by your particular value (well, the particular concrete type of your particular value). In Python we would do this either with a _hasattr()_ check or just by calling _obj.CloseWrite()_ and catching _AttributeError_, but we're in Go and Go does things differently. If you're a certain sort of [[beginning Go programmer GoFirstExperience]] coming from Python, you grind your teeth in irritation, look up just what concrete types support _.CloseWrite()_, and write the following brute force code using a [[type switch http://golang.org/ref/spec#Switch_statements]]: .pn prewrap on > func shutdownWrite(conn net.Conn) { > switch i := conn.(type) { > case *net.TCPConn: > i.CloseWrite() > case *net.UnixConn: > i.CloseWrite() > } > } (Then this code doesn't compile under Go 1.0 because _net.UnixConn_ doesn't implement _.CloseWrite()_ in Go 1.0.) What this code is doing in its brute force way is changing the type of _conn_ into something where we know that we can call _.CloseWrite()_ and where the Go compiler will let us do so. The compiler won't let us directly call _conn.CloseWrite()_ because _.CloseWrite()_ is not part of the _net.Conn_ interface, but it will let us call, say, _net.TCPConn.CloseWrite()_, because it is part of _net.TCPConn_'s public methods. So if _conn_ is actually a _net.TCPConn_ value (well, a pointer to it) we can convert its type through this type switch and then make the call. Unfortunately this code has the great drawback that it has to specifically know which concrete types that sit behind _net.Conn_ do and don't implement _.CloseWrite()_. This is bad for various reasons. (I am mangling some Go details here in the interests of nominal clarity.) The experienced Go programmers in the audience are shaking their heads sadly right now, because there is a more general and typesafe way to do this. We just need to say what we actually mean. First we need a type that will let us call _.CloseWrite()_; this has to be an interface type because we need to convert _conn_ to it (somehow). > type Closer interface { > CloseWrite() error > } (It's important to get the argument and return types exactly right even if you're going to ignore the return value.) Now we need to coerce _conn_ to having that type *if and only if this is possible*; if we blindly coerce _conn_ to this type (in one of a number of ways) we will get a runtime error when we're handed a _net.Conn_ with a concrete type that lacks a _.CloseWriter()_ method. In Go, this safe coercion is done with the two-result form of a [[type assertion http://golang.org/ref/spec#Type_assertions]]: > func shutdownWrite(conn net.Conn) { > v, ok := conn.(Closer) > if ok { > v.CloseWrite() > } > } (We can't just call _conn.CloseWrite()_ after the coercion because we haven't changed the type of _conn_ itself, we've just manufactured another variable, _v_, that has the right type.) This is both typesafe and general. Any _conn_ value of a concrete type that implements _.CloseWrite()_ will work and it will work transparently, while if _conn_ is of a concrete type that doesn't implement _.CloseWrite()_ there are no runtime panics; all of this is exactly what we want. The same technique can be used in exactly the same way to reach through any interface type to get access to any (public) methods on the underlying concrete types; set up an interface type with the methods you want, try coercing, and then call things appropriately. (I actually like this typesafe conversion and method access better than the Python equivalent because it feels less hacky and more a direct expression of what I want.) I think that it follows that any type switch code of the first form, one where you just call the same routine (or a few routines) on the new types, is a danger sign of doing things the wrong way. You probably want to use interface type conversion instead. (Had I read [[the right bit of Effective Go http://golang.org/doc/effective_go.html#conversions]] carefully I might have seen this right away, but [[Effective Go http://golang.org/doc/effective_go.html]] doesn't quite address this directly. All of this is probably obvious to experienced Go programmers.) ~~Update~~: there are several good ideas and improvements (and things I didn't know or realize) in the [[the golang reddit comments on this entry http://www.reddit.com/r/golang/comments/190c6u/go_using_type_assertions_to_safely_reach_through/]].