Go语言反射实现Http Url与Method映射

      最近使用Go语言,使用http server,做了一个简单Url到StructName/MethodName的简单映射。主要思路是将Url能够StructName/MethodName做个映射,只需在Struct中添加方法就可以添加了实现,比如localhost:9000\struct\a和localhost:9000\struct\b,若是struct需要添加可以定义新的Struct然后将新的Struct注册进去就可以。

核心代码:

type Server struct {
	allStruct map[string]*StructDefind
}

type StructDefind struct {
	name   string
	rvalue reflect.Value
	rtype  reflect.Type

	methods map[string]*Method
}

type Method struct {
	method     reflect.Method
	haveReturn bool
}

// construct method default
func NewServer() *Server {
	server := new(Server)
	server.allStruct = make(map[string]*StructDefind)

	return server
}

func (this *Server) Start(port string) error {
	return http.ListenAndServe(port, this)
}

func (this *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	//fmt.Fprintf(w, "Hello bs!")
	for _, s_define := range this.allStruct {
		for m_name, m := range s_define.methods {
			methodAccept := "/" + s_define.name + "/" + m_name
			if strings.EqualFold(methodAccept, r.URL.Path) {
				//fmt.Fprintln(w, "true")
				m.method.Func.Call([]reflect.Value{s_define.rvalue, reflect.ValueOf(w), reflect.ValueOf(r)})
			}
		}
	}
	//fmt.Fprintf(w, "finish")
}

func (this *Server) Register(object interface{}) error {
	register := new(StructDefind)
	register.methods = make(map[string]*Method)
	register.rvalue = reflect.ValueOf(object)
	register.rtype = reflect.TypeOf(object)
	register.name = reflect.Indirect(register.rvalue).Type().Name()
	if register.name == "" {
		return fmt.Errorf("no service name for type ")
	}
	for m := 0; m < register.rtype.NumMethod(); m++ {
		method := register.rtype.Method(m)
		mtype := method.Type
		mname := method.Name

		if mtype.NumIn() != 3 {
			return fmt.Errorf("method %s has wrong number of ins: %d", mname, mtype.NumIn())
		}
		for in := 0; in < mtype.NumIn(); in++ {
			fmt.Println(mtype.In(in))
		}
		reply := mtype.In(1)
		if reply.String() != "http.ResponseWriter" {
			return fmt.Errorf("%s argument type not exported: %s", mname, reply)
		}
		arg := mtype.In(2)
		if arg.String() != "*http.Request" {
			return fmt.Errorf("%s argument type not exported: %s", mname, arg)
		}
		register.methods[mname] = &Method{method, false}

	}
	this.allStruct[register.name] = register
	return nil
}

func (this *Server) AllInfo() {
	for _, s_define := range this.allStruct {
		for m_name := range s_define.methods {
			fmt.Println("struct name:" + s_define.name + " method name:" + m_name)
		}
	}
}

func Enter() {
	server := NewServer()
	fmt.Println(server.Register(new(common.Assert)))
	server.AllInfo()
	server.Start(":9000")
}

 一个Struct模型实例:

type Assert struct {
}


func (this *Assert) SayHello(w http.ResponseWriter, r *http.Request) {

	fmt.Fprintf(w, "Hello demo!")
}

查看结果:


 
 

猜你喜欢

转载自takemind.iteye.com/blog/2340914
今日推荐