Types in Go
Go 中变量拥有确定的静态类型:
type Int intvar i intvar j Int
那么,变量 i、j 分别拥有静态类型 int、Int,且由于静态类型不一致,不能互相直接赋值。
当变量类型为接口时:
package mainimport ("reflect""fmt")type person interface {Name() string}type String stringfunc (s String) Name() string {return string(s)}func main() {var p person = String("John")fmt.Println(reflect.TypeOf(p), reflect.ValueOf(p), p.Name())}// main.String John John
Value
Kind 常量
const (Invalid Kind = iotaBoolIntInt8Int16Int32Int64UintUint8Uint16Uint32Uint64UintptrFloat32Float64Complex64Complex128ArrayChanFuncInterfaceMapPtrSliceStringStructUnsafePointer)
内置类型
package mainimport ("reflect""fmt")func printValue(args ...interface{}) {for _, v := range args {doPrint(v)}}func doPrint(arg interface{}) {switch v := reflect.ValueOf(arg); v.Kind() {case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:fmt.Printf("Int value %d\n", v.Int())case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:fmt.Printf("UInt value %d\n", v.Uint())case reflect.Bool:fmt.Printf("Bool value %v\n", v.Bool())case reflect.Float32, reflect.Float64:fmt.Printf("Float value %f\n", v.Float())case reflect.String:fmt.Printf("String value %s\n", v.String())case reflect.Slice:fmt.Printf("Slice value %v\n", v)default:fmt.Printf("Unhandled kind %s\n", v.Kind())}}func main() {printValue(1, uint8(1), 1.0, true, "hello", []int{1, 2, 3})}
设置简单值
package mainimport ("reflect""fmt")func main() {i := 1v := reflect.ValueOf(i)fmt.Println("v.CanSet()", v.CanSet())pv := reflect.ValueOf(&i)fmt.Println("pv.CanSet()", pv.CanSet())pve := pv.Elem()fmt.Println("pve.CanSet()", pve.CanSet())pve.SetInt(2)fmt.Println(i)}// v.CanSet() false// pv.CanSet() false// pve.CanSet() true// 2
Struct
获取 Field、Method 等基本信息
package mainimport ("reflect""fmt")type Book struct {Name stringPrice float32visible bool}func (b Book) Description() string {return fmt.Sprintf("Book %s, Price: %2.2f", b.Name, b.Price)}func main() {book := Book{"Redis in Action", 32.0, false}v := reflect.ValueOf(book)fmt.Println(v.Type(), v.Kind())fields := v.NumField()for i := 0; i < fields; i++ {fv := v.Field(i)fmt.Printf("Field(%d) type %s, CanSet %v\n", i, fv.Type(), fv.CanSet())}fmt.Println(v.FieldByName("Price"))methods := v.NumMethod()for i := 0; i < methods; i++ {m := v.Method(i)fmt.Println(m.Type())}fmt.Println(book.Description())}// main.Book struct// Field(0) type string, CanSet false// Field(1) type float32, CanSet false// Field(2) type bool, CanSet false// 32// func() string// Book Redis in Action, Price: 32.00
修改结构体:
package mainimport ("reflect""fmt")type Book struct {Name stringPrice float32visible bool}func (b Book) Description() string {return fmt.Sprintf("Book %s, Price: %2.2f", b.Name, b.Price)}func main() {book := &Book{"Redis in Action", 32.0, false}v := reflect.ValueOf(book).Elem()fmt.Println(v.Type(), v.Kind())fields := v.NumField()for i := 0; i < fields; i++ {fv := v.Field(i)fmt.Printf("Field(%d) type %s, CanSet %v\n", i, fv.Type(), fv.CanSet())}v.FieldByName("Price").SetFloat(36.0)fmt.Println(book.Description())}// main.Book struct// Field(0) type string, CanSet true// Field(1) type float32, CanSet true// Field(2) type bool, CanSet false// Book Redis in Action, Price: 36.00
Slice
package mainimport ("reflect""fmt")func main() {s := []int{10, 20}t := reflect.TypeOf(s)v := reflect.ValueOf(s)fmt.Printf("Slice Type(%s), Kind(%s), Len(%d), Cap(%d), CanSet(%v)\n", t, v.Kind(), v.Len(), v.Cap(), v.CanSet())for i := 0; i < v.Len(); i++ {f := v.Index(i)fmt.Printf("Field(%d), Value(%d), CanSet(%v)\n", i, f.Int(), f.CanSet())f.SetInt(f.Int() + 1)}fmt.Println(s)}// Slice Type([]int), Kind(slice), Len(2), Cap(2), CanSet(false)// Field(0), Value(10), CanSet(true)// Field(1), Value(20), CanSet(true)// [11 21]
Append 操作
package mainimport ("reflect""fmt")func main() {s := []int{1, 2}v := reflect.ValueOf(&s).Elem()fmt.Printf("Slice Type(%s), Kind(%s), Len(%d), Cap(%d), CanSet(%v)\n", v.Type(), v.Kind(), v.Len(), v.Cap(), v.CanSet())v.Set(reflect.Append(v, reflect.ValueOf(3), reflect.ValueOf(4), reflect.ValueOf(5)))fmt.Printf("Slice Type(%s), Kind(%s), Len(%d), Cap(%d), CanSet(%v)\n", v.Type(), v.Kind(), v.Len(), v.Cap(), v.CanSet())fmt.Println(s)}// Slice Type([]int), Kind(slice), Len(2), Cap(2), CanSet(true)// Slice Type([]int), Kind(slice), Len(5), Cap(8), CanSet(true)// [1 2 3 4 5]
Map
package mainimport ("reflect""fmt")func keys(v reflect.Value) []reflect.Value {return v.MapKeys()}func main() {s := map[string]int64{"A": 100,"B": 80,}v := reflect.ValueOf(&s).Elem()fmt.Printf("Map Type(%s), Kind(%s), Key(%s), Len(%d), CanSet(%v)\n", v.Type(), v.Kind(), v.Type().Key(), v.Len(), v.CanSet())for _, k := range keys(v) {fmt.Printf("Key(%s), Value(%d), CanSet(%v)\n", k, v.MapIndex(k).Int(), v.MapIndex(k).CanSet())v.SetMapIndex(k, reflect.ValueOf(v.MapIndex(k).Int() * 2))}v.SetMapIndex(reflect.ValueOf("C"), reflect.ValueOf(int64(60)))fmt.Println(s)}// Map Type(map[string]int64), Kind(map), Key(string), Len(2), CanSet(true)// Key(A), Value(100), CanSet(false)// Key(B), Value(80), CanSet(false)// map[A:200 B:160 C:60]
Function
package mainimport ("reflect""fmt")func incr(v int) (int, error) {return v + 1, nil}func main() {t := reflect.TypeOf(incr)fmt.Printf("Function type [%v], in:[%d], out(%d), Name(%s)\n", t, t.NumIn(), t.NumOut(), t.Name())for i := 0; i < t.NumIn(); i++ {fmt.Printf("args[%d], Name(%s), Kind(%s)\n", i, t.In(i).Name(), t.In(i).Kind())}for i := 0; i < t.NumOut(); i++ {fmt.Printf("returns[%d], Name(%s), Kind(%s)\n", i, t.Out(i).Name(), t.Out(i).Kind())}fmt.Println("Comparable:", t.Comparable())}// Function type [func(int) (int, error)], in:[1], out(2), Name()// args[0], Name(int), Kind(int)// returns[0], Name(int), Kind(int)// returns[1], Name(error), Kind(interface)// Comparable: false
反射中调用函数
package mainimport ("reflect""fmt")func incr(v int) (int, error) {return v + 1, nil}func main() {t := reflect.TypeOf(incr)v := reflect.ValueOf(incr)outs := v.Call([]reflect.Value{reflect.ValueOf(1)})ev := outs[t.NumOut() - 1]if t.Out(t.NumOut() - 1).Name() == "error" && ev.IsNil() {fmt.Println(outs[0])} else {fmt.Println(ev)}}// 2
Channel
package mainimport ("fmt""reflect""time")func read(v reflect.Value) reflect.SelectCase {return reflect.SelectCase{Dir: reflect. SelectRecv,Chan: v,}}func write(ch, v reflect.Value) {ch.Send(v)}func main() {ch := make(chan int, 4)stop := make(chan struct{})go func() {sels := []reflect.SelectCase{}sels = append(sels, read(reflect.ValueOf(ch)))sels = append(sels, read(reflect.ValueOf(stop)))for {c, rv, ok := reflect.Select(sels)if !ok {break}if c == 1 { // stop channel receivedbreak}fmt.Printf("Received from Index(%d) with Value(%v)\n", c, rv)}}()write(reflect.ValueOf(ch), reflect.ValueOf(1))write(reflect.ValueOf(ch), reflect.ValueOf(2))write(reflect.ValueOf(ch), reflect.ValueOf(3))write(reflect.ValueOf(ch), reflect.ValueOf(4))time.Sleep(1 * time.Second)close(stop)}// Received from Index(0) with Value(1)// Received from Index(0) with Value(2)// Received from Index(0) with Value(3)// Received from Index(0) with Value(4)
