站点更新:2018-01-29 12:47:06
This commit is contained in:
parent
ca2738072a
commit
eeb4d31572
127
common/reflect/main.go
Normal file
127
common/reflect/main.go
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Age int `json:"age" default:"18"`
|
||||||
|
addr string `json:"addr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u User) Do(in string) (string, int) {
|
||||||
|
fmt.Printf("%s Name is %s, Age is %d \n", in, u.Name, u.Age)
|
||||||
|
return u.Name, u.Age
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
u := User{"tom", 27, "beijing"}
|
||||||
|
|
||||||
|
// 获取对象的 Value
|
||||||
|
v := reflect.ValueOf(u)
|
||||||
|
fmt.Println("Value:", v)
|
||||||
|
// fmt.Printf("%v\n", u)
|
||||||
|
|
||||||
|
// 获取对象的 Type
|
||||||
|
t := reflect.TypeOf(u)
|
||||||
|
fmt.Println("Type:", t)
|
||||||
|
// fmt.Printf("%T\n", u)
|
||||||
|
|
||||||
|
t1 := v.Type()
|
||||||
|
fmt.Println(t == t1)
|
||||||
|
|
||||||
|
v1 := reflect.New(t)
|
||||||
|
fmt.Println(v1)
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
// 获取 Kind 类型
|
||||||
|
k := t.Kind()
|
||||||
|
fmt.Println("Kind:", k)
|
||||||
|
k1 := v.Kind()
|
||||||
|
fmt.Println(k == k1)
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
// 修改反射对象的值
|
||||||
|
i := 20
|
||||||
|
fmt.Println("before i =", i)
|
||||||
|
e := reflect.Indirect(reflect.ValueOf(&i))
|
||||||
|
// e := reflect.ValueOf(&i).Elem()
|
||||||
|
if e.CanSet() {
|
||||||
|
e.SetInt(22)
|
||||||
|
}
|
||||||
|
fmt.Println("after i =", i)
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
// 反射字段操作
|
||||||
|
// elem := reflect.Indirect(reflect.ValueOf(&u))
|
||||||
|
elem := reflect.ValueOf(&u).Elem()
|
||||||
|
for i := 0; i < t.NumField(); i++ {
|
||||||
|
// 反射获取字段的元信息,例如:名称、Tag 等
|
||||||
|
ft := t.Field(i)
|
||||||
|
fmt.Println("field name:", ft.Name)
|
||||||
|
tag := ft.Tag
|
||||||
|
fmt.Println("Tag:", tag)
|
||||||
|
fmt.Println("Tag json:", tag.Get("json"))
|
||||||
|
|
||||||
|
// 反射修改字段的值
|
||||||
|
fv := elem.Field(i)
|
||||||
|
if fv.CanSet() {
|
||||||
|
if fv.Kind() == reflect.Int {
|
||||||
|
fmt.Println("change age to 30")
|
||||||
|
fv.SetInt(30)
|
||||||
|
}
|
||||||
|
if fv.Kind() == reflect.String {
|
||||||
|
fmt.Println("change name to jerry")
|
||||||
|
fv.SetString("jerry")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
fmt.Println("after user:", u)
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
// 反射方法操作
|
||||||
|
for i := 0; i < v.NumMethod(); i++ {
|
||||||
|
method := t.Method(i) // 获取方法信息对象,方法 1
|
||||||
|
mt := method.Type // 获取方法信息 Type 对象,方法 1
|
||||||
|
|
||||||
|
// m := v.Method(i) // 获取方法信息对象,方法 2
|
||||||
|
// mt := m.Type() // 获取方法信息 Type 对象,方法 2
|
||||||
|
|
||||||
|
fmt.Println("method name:", method.Name)
|
||||||
|
|
||||||
|
in := []reflect.Value{}
|
||||||
|
|
||||||
|
// 获取方法入参类型
|
||||||
|
for j := 0; j < mt.NumIn(); j++ {
|
||||||
|
fmt.Println("method in type:", mt.In(j))
|
||||||
|
if mt.In(j).Kind() == reflect.String {
|
||||||
|
in = append(in, reflect.ValueOf("welcome"))
|
||||||
|
}
|
||||||
|
// 方法 1 获取的方法信息对象会把方法的接受者也当着入参之一
|
||||||
|
if mt.In(j).Name() == t.Name() {
|
||||||
|
in = append(in, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取方法返回类型
|
||||||
|
for j := 0; j < mt.NumOut(); j++ {
|
||||||
|
fmt.Println("method out type:", mt.Out(j))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 反射方法调用
|
||||||
|
// out := m.Call(in) // 方法 1 获取的 Method 对象反射调用方式
|
||||||
|
out := method.Func.Call(in) // 方法 1 获取的 Method 对象反射调用方式
|
||||||
|
for _, o := range out {
|
||||||
|
fmt.Println("out:", o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
// Value 转原始类型
|
||||||
|
if u1, ok := v.Interface().(User); ok {
|
||||||
|
fmt.Println("after:", u1.Name, u1.Age)
|
||||||
|
}
|
||||||
|
}
|
31
common/server/client/main.go
Normal file
31
common/server/client/main.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/ehlxr/go-utils/common/server"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
server := server.NewServer()
|
||||||
|
err := server.Register(new(Hello))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
err = server.Start(":8080")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Hello struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Hello) Print(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Write([]byte("print"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Hello) Hello(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Write([]byte("hello"))
|
||||||
|
}
|
67
common/server/server.go
Normal file
67
common/server/server.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
name string
|
||||||
|
val reflect.Value
|
||||||
|
typ reflect.Type
|
||||||
|
methods []reflect.Method
|
||||||
|
lock sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewServer() *Server {
|
||||||
|
server := new(Server)
|
||||||
|
server.methods = make([]reflect.Method, 0)
|
||||||
|
return server
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) Start(addr string) error {
|
||||||
|
log.Println(fmt.Sprintf("server start on addr [%s]", addr))
|
||||||
|
return http.ListenAndServe(addr, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
for _, method := range s.methods {
|
||||||
|
if strings.ToLower("/"+s.name+"/"+method.Name) == r.URL.Path {
|
||||||
|
method.Func.Call([]reflect.Value{s.val, reflect.ValueOf(w), reflect.ValueOf(r)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) Register(service interface{}) error {
|
||||||
|
s.lock.Lock()
|
||||||
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
|
s.typ = reflect.TypeOf(service)
|
||||||
|
s.val = reflect.ValueOf(service)
|
||||||
|
s.name = reflect.Indirect(s.val).Type().Name()
|
||||||
|
if s.name == "" {
|
||||||
|
return fmt.Errorf("no service name for type %s", s.typ.String())
|
||||||
|
}
|
||||||
|
for m := 0; m < s.typ.NumMethod(); m++ {
|
||||||
|
method := s.typ.Method(m)
|
||||||
|
mtype := method.Type
|
||||||
|
if mtype.NumIn() != 3 {
|
||||||
|
return fmt.Errorf("method %s has wrong number of ins: %d", method.Name, mtype.NumIn())
|
||||||
|
}
|
||||||
|
reply := mtype.In(1)
|
||||||
|
if reply.String() != "http.ResponseWriter" {
|
||||||
|
return fmt.Errorf("%s argument type not exported: %s", method.Name, reply)
|
||||||
|
}
|
||||||
|
arg := mtype.In(2)
|
||||||
|
if arg.String() != "*http.Request" {
|
||||||
|
return fmt.Errorf("%s argument type not exported: %s", method.Name, arg)
|
||||||
|
}
|
||||||
|
s.methods = append(s.methods, method)
|
||||||
|
log.Println("registry path:", strings.ToLower("/"+s.name+"/"+method.Name))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user