最近使用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!")
}
查看结果: