go 的 struct 的属性字段更新, 使用反射
package main
import (
"fmt"
"reflect"
)
type Movie struct {
Title, Subtitle string
Year int
Color bool
Actor map[string]string
Oscars []string
Sequel *string
}
func main() {
strangelove := Movie{
Title: "Dr. Strangelove",
Subtitle: "How i Learned to Stop Worrying and Love the Bomb",
Year: 1964,
Color: false,
Actor: map[string]string{
"Dr. Strangelove": "Peter Sellers",
"Grp. Capt. Lionel Mandrake": "Peter Sellers",
"Pres. Merkin Muffley": "Peter Sellers",
"Gen. Buck Turgidson": "George C. Scott",
"Brig. Gen. Jack D. Ripper": "Sterling Hayden",
`Maj. T.J. "King" Kong`: "Slim Pickens",
},
Oscars : []string{
"Best Actor (Nomin.)",
"Best Adapted Screenplay (Nomin.)",
"Best Director (Nomin.)",
"Best Picture (Nomin.)",
},
}
Display("strangelove", strangelove)
}
func Display(name string, x interface{}) {
fmt.Printf("Display %s (%T):\n", name, x)
display(name, reflect.ValueOf(x))
}
func display(path string, v reflect.Value) {
switch v.Kind() {
case reflect.Invalid:
fmt.Printf("%s = invalid\n", path)
case reflect.Slice, reflect.Array:
for i := 0; i < v.Len(); i++ {
display(fmt.Sprintf("%s[%d]", path, i), v.Index(i))
}
case reflect.Struct:
for i := 0; i < v.NumField(); i++ {
fieldPath := fmt.Sprintf("%s.%s", path, v.Type().Field(i).Name)
display(fieldPath, v.Field(i))
}
case reflect.Map:
for _, key := range v.MapKeys() {
display(fmt.Sprintf("%s[%s]", path, key), v.MapIndex(key))
}
case reflect.Ptr:
if v.IsNil() {
fmt.Printf("%s = nil\n", path)
} else {
display(fmt.Sprintf("(*%s)", path), v.Elem())
}
case reflect.Interface:
if v.IsNil() {
fmt.Printf("%s = nil\n", path)
} else {
fmt.Printf("%s.type = %s\n", path, v.Elem().Type())
display(path+".value", v.Elem())
}
default:
fmt.Printf("%s = %v\n", path, v)
}
}
package main
import (
"reflect"
"strconv"
"time"
"fmt"
)
func main() {
var x int64 = 1
var d time.Duration = 1* time.Nanosecond
fmt.Println(Any(x))
fmt.Println(Any(d))
fmt.Println(Any([]int64{x}))
fmt.Println(Any([]time.Duration{d}))
}
func Any(value interface{}) string {
return formatAtom(reflect.ValueOf(value))
}
func formatAtom(v reflect.Value) string {
switch v.Kind() {
case reflect.Invalid:
return "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() + " 0x" + strconv.FormatUint(uint64(v.Pointer()), 16)
default:
return v.Type().String() + " value"
}
}
func (this *NetStat) sub(before *NetStat) *NetStat {
if before == nil {
return nil
}
result := &NetStat{}
elem := reflect.ValueOf(this).Elem()
elemResult := reflect.ValueOf(result).Elem()
elemBefore := reflect.ValueOf(before).Elem()
for i := 0; i < elem.NumField(); i++ {
elemResult.Field(i).SetUint(elem.Field(i).Uint() - elemBefore.Field(i).Uint())
}
return result
}