《The Go Programming Language》笔记
Golang的反射由reflect包提供支持,有两个重要类型:一个Type表示一个Go类型,它是一个接口。一个Value可以持有任意类型的值。
import (
@H_301_6@"fmt"
@H_301_6@"reflect"
@H_301_6@"strconv"
)
func Display(name string,x interface{}) {
fmt.Printf(@H_301_6@"Display %s (%T):\n",name,x)
display(name,reflect.ValueOf(x))
}
func formatAtom(v reflect.Value) string {
switch v.Kind() {
case reflect.Invalid:
return @H_301_6@"invalid"
case reflect.Int,reflect.Int8,reflect.Int16,reflect.Int32,reflect.Int64:
return strconv.FormatInt(v.Int(),10)
case reflect.Uint,reflect.Uint8,reflect.Uint16,reflect.Uint32,reflect.Uint64:
return strconv.FormatUint(v.Uint(),10)
case reflect.Bool:
return strconv.FormatBool(v.Bool())
case reflect.String:
return strconv.Quote(v.String())
case reflect.Chan,reflect.Func,reflect.Ptr,reflect.Slice,reflect.Map:
return v.Type().String() + @H_301_6@"0x" + strconv.FormatUint(uint64(v.Pointer()),16)
default:
return v.Type().String() + @H_301_6@"value"
}
}
func display(path string,v reflect.Value) {
switch v.Kind() {
case reflect.Invalid:
fmt.Printf(@H_301_6@"%s = invalid\n",path)
case reflect.Slice,reflect.Array:
for i := 0; i < v.Len(); i++ {
display(fmt.Sprintf(@H_301_6@"%s[%d]",path,i),v.Index(i))
}
case reflect.Struct:
for i := 0; i < v.NumField(); i++ {
fieldPath := fmt.Sprintf(@H_301_6@"%s.%s",v.Type().Field(i).Name)
display(fieldPath,v.Field(i))
}
case reflect.Map:
for _,key := range v.MapKeys(){
display(fmt.Sprintf(@H_301_6@"%s[%s]",formatAtom(key)),v.MapIndex(key))
}
case reflect.Ptr:
if v.IsNil() {
fmt.Printf(@H_301_6@"%s = nil\n",path)
} else {
display(fmt.Sprintf(@H_301_6@"*%s",path),v.Elem())
}
case reflect.Interface:
if v.IsNil() {
fmt.Printf(@H_301_6@"%s = nil\n",path)
} else {
fmt.Printf(@H_301_6@"%s.type = %s\n",v.Elem().Type())
display(path+@H_301_6@".value",v.Elem())
}
default:
fmt.Printf(@H_301_6@"%s = %s\n",formatAtom(v))
}
}
import @H_301_6@"testing"
type Movie struct {
Title,Subtitle string
Year int
Color bool
Actor map[string]string
Oscars []string
Sequel *string
}
var strangelove = Movie{
Title: @H_301_6@"Dr. Strangelove",Subtitle: @H_301_6@"How I Learned to Stop Worrying and Love the Bomb",Year: 1964,Color: false,Actor: map[string]string{
@H_301_6@"Dr. Strangelove": @H_301_6@"Peter Sellers",@H_301_6@"Grp. Cat. Lionel Mandrake": @H_301_6@"Peter Sellers",@H_301_6@"Gen. Buck Turgidson": @H_301_6@"George Hayden",},Oscars: []string{
@H_301_6@"Best Actor (Nomin.)",@H_301_6@"Best Adapted Screeenplay (Nomin.)",}
func TestDisplay(t *testing.T) {
Display(@H_301_6@"strangelove",strangelove)
}
Display strangelove (main.Movie): strangelove.Title = “Dr. Strangelove” strangelove.Subtitle = “How I Learned to Stop Worrying and Love the Bomb” strangelove.Year = 1964 strangelove.Color = false strangelove.Actor[“Dr. Strangelove”] = “Peter Sellers” strangelove.Actor[“Grp. Cat. Lionel Mandrake”] = “Peter Sellers” strangelove.Actor[“Gen. Buck Turgidson”] = “George Hayden” strangelove.Oscars[0] = “Best Actor (Nomin.)” strangelove.Oscars[1] = “Best Adapted Screeenplay (Nomin.)” strangelove.Sequel = nil