]> Cypherpunks repositories - gostls13.git/commitdiff
handle the nil interface better in reflect and print
authorRob Pike <r@golang.org>
Thu, 11 Dec 2008 20:59:49 +0000 (12:59 -0800)
committerRob Pike <r@golang.org>
Thu, 11 Dec 2008 20:59:49 +0000 (12:59 -0800)
R=rsc
DELTA=25  (19 added, 0 deleted, 6 changed)
OCL=20985
CL=20985

src/lib/fmt/print.go
src/lib/reflect/type.go
src/lib/reflect/value.go

index c05067eb350ea4b116e341d4242824c4ded8b1ff..9c1b0ddfcd919ec0674a405600ced29f220c655f 100644 (file)
@@ -307,9 +307,12 @@ func parsenum(s string, start, end int) (n int, got bool, newi int) {
 }
 
 func (p *P) printField(field reflect.Value) (was_string bool) {
-       if stringer, ok := field.Interface().(String); ok {
-               p.addstr(stringer.String());
-               return false;   // this value is not a string
+       inter := field.Interface();
+       if inter != nil {
+               if stringer, ok := inter.(String); ok {
+                       p.addstr(stringer.String());
+                       return false;   // this value is not a string
+               }
        }
        s := "";
        switch field.Kind() {
@@ -363,6 +366,14 @@ func (p *P) printField(field reflect.Value) (was_string bool) {
                p.add('{');
                p.doprint(field, true, false);
                p.add('}');
+       case reflect.InterfaceKind:
+               inter := field.(reflect.InterfaceValue).Get();
+               if inter == nil {
+                       s = "<nil>"
+               } else {
+                       // should never happen since a non-nil interface always has a type
+                       s = "<non-nil interface>";
+               }
        default:
                s = "?" + field.Type().String() + "?";
        }
@@ -421,8 +432,9 @@ func (p *P) doprintf(format string, v reflect.StructValue) {
                }
                field := getField(v, fieldnum);
                fieldnum++;
-               if c != 'T' {   // don't want thing to describe itself if we're asking for its type
-                       if formatter, ok := field.Interface().(Format); ok {
+               inter := field.Interface();
+               if inter != nil && c != 'T' {   // don't want thing to describe itself if we're asking for its type
+                       if formatter, ok := inter.(Format); ok {
                                formatter.Format(p, c);
                                continue;
                        }
index dc1a30a5ad773b221950b6b0da33c8c65c9a6ec5..ce44ecf937d2d73eeae2b64a9f817b6d29b26512 100644 (file)
@@ -340,6 +340,8 @@ func (t *InterfaceTypeStruct) Len() int {
        return len(t.field)
 }
 
+var NilInterface = NewInterfaceTypeStruct("nil", "", new([]Field, 0));
+
 // -- Func
 
 export type FuncType interface {
@@ -834,6 +836,10 @@ func (p *Parser) Type(name string) *StubType {
 }
 
 export func ParseTypeString(name, typestring string) Type {
+       if typestring == "" {
+               // If the typestring is empty, it represents (the type of) a nil interface value
+               return NilInterface
+       }
        p := new(Parser);
        p.str = typestring;
        p.Next();
index 1b6ec314636a285fc1259e95a6877a1c2661f151..9df6c62315587e832e977ddec02c3c70363353cb 100644 (file)
@@ -59,6 +59,7 @@ type Creator *(typ Type, addr Addr) Value
 export type MissingValue interface {
        Kind()  int;
        Type()  Type;
+       Addr()  Addr;
 }
 
 type MissingValueStruct struct {
@@ -66,7 +67,7 @@ type MissingValueStruct struct {
 }
 
 func MissingCreator(typ Type, addr Addr) Value {
-       return &MissingValueStruct{ Common{IntKind, typ, addr} }
+       return &MissingValueStruct{ Common{MissingKind, typ, addr} }
 }
 
 // -- Int