Types in Go
Go 中变量拥有确定的静态类型:
type Int int
var i int
var j Int
那么,变量 i、j 分别拥有静态类型 int、Int,且由于静态类型不一致,不能互相直接赋值。
当变量类型为接口时:
package main
import (
"reflect"
"fmt"
)
type person interface {
Name() string
}
type String string
func (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 = iota
Bool
Int
Int8
Int16
Int32
Int64
Uint
Uint8
Uint16
Uint32
Uint64
Uintptr
Float32
Float64
Complex64
Complex128
Array
Chan
Func
Interface
Map
Ptr
Slice
String
Struct
UnsafePointer
)
内置类型
package main
import (
"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 main
import (
"reflect"
"fmt"
)
func main() {
i := 1
v := 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 main
import (
"reflect"
"fmt"
)
type Book struct {
Name string
Price float32
visible 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 main
import (
"reflect"
"fmt"
)
type Book struct {
Name string
Price float32
visible 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 main
import (
"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 main
import (
"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 main
import (
"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 main
import (
"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 main
import (
"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 main
import (
"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 received
break
}
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)