Given
var r io.Reader
one can write
_, _ = r.(io.Writer)
but not
switch r.(type) {
case io.Writer:
}
The type switch results in "impossible type switch
case: r (type io.Reader) cannot have dynamic type
io.Writer (missing Read method)". But I think that
the concrete value r points to can have dynamic type
io.Writer, so I'm a little confused.
What am I missing?
kr
I'm not so sure. For instance, it prevents you from type switching with a case for Hijacker or Flusher or StringWriter when you have one of the more basic writers. I can't seem to find the change in which this was introduced, which may explain the reason for it.
(sent from gmail mobile)
(Not tested, typing on a phone)
This is a bug in the compiler. I noticed this a few days
ago, and I'm not sure when it went in. The workaround,
as others have noted, is to write an if statement instead
(or to say case interface { Reader; Writer }:).
Will be fixed soon. Sorry about the trouble.
Russ
> r's (concrete interface) type statically restricts its method set, type switch on r is just pointless.
I disagree. The interface type specifies a minimum requirement for functionality. The algorithm may be able to use a more specialized interface to run more efficiently, and resort to the original interface type only in the general case. If you have multiple possible special cases you want to handle, switching on a value of non-empty interface type is reasonable.
> What might work as probably intended is something like"switch x := interface{}(r); x.(type) { ... }"
It would have to, or else fmt wouldn't work. The boundary cases should not behave differently from every other case. There is no reason for an empty interface to work differently from every other interface. This must be a bug.
FWIW, went in on the first appearance of the check:
changeset: 10380:e19afb349d0e
user: Luuk van Dijk <l...@golang.org>
date: Wed Nov 09 10:58:53 2011 +0100
summary: gc: Better typechecks and errors in switches.
--
Gustavo Niemeyer
http://niemeyer.net
http://niemeyer.net/plus
http://niemeyer.net/twitter
http://niemeyer.net/blog
-- I'm not absolutely sure of anything.
This is a bug in the compiler. I noticed this a few days
ago, and I'm not sure when it went in. The workaround,
as others have noted, is to write an if statement instead
(or to say case interface { Reader; Writer }:).
I disagree.
On Jan 14, 12:04 am, Jan Mercl <jan....@nic.cz> wrote:
> r's (concrete interface) type statically restricts its method set, type switch on r is just pointless.
This sentence contradicts the language specification.
There is no such thing as "restricts its method set" in Go. There is
"partial information about the full method set of a particular non-
interface type".
var r io.Reader
tty, err = os.OpenFile("/dev/tty", os.O_RDWR, 0)
if err != nil { return nil, err }
r = tty
r contains, schematically, the (value, type) pair, (tty, *os.File). Notice that the type *os.Fileimplements methods other than Read; even though the interface value provides access only to the Read method, the value inside carries all the type information about that value. That's why we can do things like this:var w io.Writer
w = r.(io.Writer)
The expression in this assignment is a type assertion; what it asserts is that the item insideralso implementsio.Writer, and so we can assign it tow. After the assignment,wwill contain the pair (tty,*os.File). That's the same pair as was held inr. The static type of the interface determines what methods may be invoked with an interface variable, even though the concrete value inside may have a larger set of methods.
Read method ..." and "The *static* type of the interface determines ..." parts talks about the same thing I called "restriction" or "statically restricted" - as in contrast to "dynamic restriction" (must satisfy the method set) like seen in the type assertion with w.