Ver código fonte

新增命令行支持参数

lxg 3 anos atrás
pai
commit
adc810093d

+ 7 - 0
cmd/main.go

@@ -4,6 +4,7 @@ import (
 	"context"
 	"fmt"
 	"git.nspix.com/golang/micro"
+	"git.nspix.com/golang/micro/gateway/cli"
 	"git.nspix.com/golang/micro/helper/console"
 	"math/rand"
 	"time"
@@ -60,6 +61,12 @@ func main() {
 		})
 	}()
 
+	time.AfterFunc(time.Second*10, func() {
+		svr.CliServe().Handle("/show/user/:uid", func(ctx *cli.Context) (err error) {
+			return ctx.Success(ctx.ParamValue("uid"))
+		})
+	})
+
 	if err := svr.Run(); err != nil {
 		fmt.Println(err)
 	}

+ 23 - 0
gateway/cli/context.go

@@ -8,6 +8,7 @@ import (
 	"git.nspix.com/golang/micro/helper/utils"
 	"reflect"
 	"strconv"
+	"strings"
 	"sync"
 )
 
@@ -24,6 +25,7 @@ type Context struct {
 	ID       int32
 	CmdStr   string
 	Args     []string //所有参数
+	params   []string
 	locker   sync.RWMutex
 	Values   map[string]interface{}
 	response *Response
@@ -43,6 +45,26 @@ func (ctx *Context) HasArgument(i int) bool {
 	return len(ctx.Args) > i
 }
 
+//ParamValue 获取参数的值
+func (ctx *Context) ParamValue(name string) string {
+	idx := -1
+	if ctx.params == nil {
+		return ""
+	}
+	for i, s := range ctx.params {
+		if strings.ToLower(s) == strings.ToLower(name) {
+			idx = i
+			break
+		}
+	}
+	if idx > -1 {
+		if ctx.HasArgument(idx) {
+			return ctx.Argument(idx)
+		}
+	}
+	return ""
+}
+
 //Argument 获取指定参数
 func (ctx *Context) Argument(i int) string {
 	if ctx.HasArgument(i) {
@@ -54,6 +76,7 @@ func (ctx *Context) Argument(i int) string {
 func (ctx *Context) reset(s string) {
 	ctx.response = &Response{}
 	ctx.Args = nil
+	ctx.params = nil
 	ctx.CmdStr = s
 }
 

+ 17 - 6
gateway/cli/executor.go

@@ -26,6 +26,7 @@ type Executor struct {
 	createdTime    time.Time
 	seq            int64
 	locker         sync.RWMutex
+	params         []string //params (eg: /show/user/:uid => :uid)
 	NotFoundHandle func(ctx *Context, cmd string) (*Response, error)
 }
 
@@ -188,13 +189,23 @@ func (exec *Executor) Do(ctx *Context, args ...string) (res *Response, err error
 		}
 		return
 	}
-	ctx.Args = args
-	if err = exec.handleFunc(ctx); err == nil {
-		res = ctx.response
+	if len(exec.params) > 0 && len(args) < len(exec.params) {
+		s := ""
+		for _, v := range exec.params {
+			s += "{" + v + "} "
+		}
+		res = &Response{Code: 1000, Error: fmt.Sprintf("Usage: %s %s", ctx.CmdStr, s)}
+		err = nil
 	} else {
-		if err == ErrInvalidArgument {
-			res = &Response{Code: 1000, Error: fmt.Sprint(ctx.Get("usage"))}
-			err = nil
+		ctx.Args = args
+		ctx.params = exec.params
+		if err = exec.handleFunc(ctx); err == nil {
+			res = ctx.response
+		} else {
+			if err == ErrInvalidArgument {
+				res = &Response{Code: 1000, Error: fmt.Sprint(ctx.Get("usage"))}
+				err = nil
+			}
 		}
 	}
 	return

+ 11 - 0
gateway/cli/server.go

@@ -131,6 +131,17 @@ func (svr *Server) Handle(path string, cb HandleFunc) {
 		if token == "" {
 			continue
 		}
+		//处理参数
+		if strings.HasPrefix(token, ":") {
+			if p != nil {
+				if p.params == nil {
+					p.params = make([]string, 0, 10)
+				}
+				p.params = append(p.params, token[1:])
+				p.handleFunc = cb
+			}
+			continue
+		}
 		if q, err = p.Children(token); err == nil {
 			if i == length-1 {
 				panic(path + " already exists")

+ 22 - 0
helper/pool/bufferpoll/pool.go

@@ -0,0 +1,22 @@
+package bufferpoll
+
+import (
+	"bytes"
+	"sync"
+)
+
+var (
+	bufferPool sync.Pool
+)
+
+func Get() *bytes.Buffer {
+	if v := bufferPool.Get(); v != nil {
+		return v.(*bytes.Buffer)
+	}
+	return bytes.NewBuffer([]byte{})
+}
+
+func Put(b *bytes.Buffer) {
+	b.Reset()
+	bufferPool.Put(b)
+}

+ 50 - 0
helper/pool/bytepoll/pool.go

@@ -0,0 +1,50 @@
+package bytepoll
+
+import "sync"
+
+var (
+	bufPool5k sync.Pool
+	bufPool2k sync.Pool
+	bufPool1k sync.Pool
+	bufPool   sync.Pool
+)
+
+func Get(size int) []byte {
+	if size <= 0 {
+		return nil
+	}
+	var x interface{}
+	if size >= 5*1024 {
+		x = bufPool5k.Get()
+	} else if size >= 2*1024 {
+		x = bufPool2k.Get()
+	} else if size >= 1*1024 {
+		x = bufPool1k.Get()
+	} else {
+		x = bufPool.Get()
+	}
+	if x == nil {
+		return make([]byte, size)
+	}
+	buf := x.([]byte)
+	if cap(buf) < size {
+		return make([]byte, size)
+	}
+	return buf[:size]
+}
+
+func Put(buf []byte) {
+	size := cap(buf)
+	if size <= 0 {
+		return
+	}
+	if size >= 5*1024 {
+		bufPool5k.Put(buf)
+	} else if size >= 2*1024 {
+		bufPool2k.Put(buf)
+	} else if size >= 1*1024 {
+		bufPool1k.Put(buf)
+	} else {
+		bufPool.Put(buf)
+	}
+}

+ 4 - 0
log/logger.go

@@ -51,6 +51,10 @@ func getLevelText(lv int) string {
 	}
 }
 
+func FormatLevel(lv int) string {
+	return getLevelText(lv)
+}
+
 func ParseLevel(s string) (lv int) {
 	lv = DebugLevel
 	s = strings.ToUpper(s)

+ 121 - 0
log/loghub.go

@@ -0,0 +1,121 @@
+package log
+
+import (
+	"bytes"
+	"encoding/binary"
+	"fmt"
+	"git.nspix.com/golang/micro/helper/pool/bufferpoll"
+	"net"
+	"os"
+	"time"
+)
+
+type LogHub struct {
+	level   int
+	appName string
+	prefix  string
+	conn    *net.UDPConn
+}
+
+func (lg *LogHub) SetLevel(i int) {
+	lg.level = i
+}
+
+func (lg *LogHub) Prefix(s string) {
+	lg.prefix = s
+}
+
+func (lg *LogHub) Print(i ...interface{}) {
+	lg.write(TraceLevel, fmt.Sprint(i...))
+}
+
+func (lg *LogHub) Printf(format string, args ...interface{}) {
+	lg.write(TraceLevel, fmt.Sprintf(format, args...))
+}
+
+func (lg *LogHub) Debug(i ...interface{}) {
+	lg.write(DebugLevel, fmt.Sprint(i...))
+}
+
+func (lg *LogHub) Debugf(format string, args ...interface{}) {
+	lg.write(DebugLevel, fmt.Sprintf(format, args...))
+}
+
+func (lg *LogHub) Info(i ...interface{}) {
+	lg.write(InfoLevel, fmt.Sprint(i...))
+}
+
+func (lg *LogHub) Infof(format string, args ...interface{}) {
+	lg.write(InfoLevel, fmt.Sprintf(format, args...))
+}
+
+func (lg *LogHub) Warn(i ...interface{}) {
+	lg.write(WarnLevel, fmt.Sprint(i...))
+}
+
+func (lg *LogHub) Warnf(format string, args ...interface{}) {
+	lg.write(WarnLevel, fmt.Sprintf(format, args...))
+}
+
+func (lg *LogHub) Error(i ...interface{}) {
+	lg.write(ErrorLevel, fmt.Sprint(i...))
+}
+
+func (lg *LogHub) Errorf(format string, args ...interface{}) {
+	lg.write(ErrorLevel, fmt.Sprintf(format, args...))
+}
+
+func (lg *LogHub) Fatal(i ...interface{}) {
+	lg.write(FatalLevel, fmt.Sprint(i...))
+}
+
+func (lg *LogHub) Fatalf(format string, args ...interface{}) {
+	lg.write(FatalLevel, fmt.Sprintf(format, args...))
+}
+
+func (lg *LogHub) Panic(i ...interface{}) {
+	lg.write(PanicLevel, fmt.Sprint(i...))
+}
+
+func (lg *LogHub) Panicf(format string, args ...interface{}) {
+	lg.write(PanicLevel, fmt.Sprintf(format, args...))
+}
+
+func (lg *LogHub) write(level int, s string) {
+	if lg.level > level {
+		return
+	}
+	var (
+		ls string
+		bf *bytes.Buffer
+	)
+	if lg.prefix != "" {
+		ls += " [" + lg.prefix + "] "
+	}
+	ls += s
+	bf = bufferpoll.Get()
+	defer bufferpoll.Put(bf)
+	// | 1byte level | 8 bytes timestamp | 1 byte name length | n byte name | 2 byte content length | n byte content |
+	bf.WriteByte(uint8(level))
+	_ = binary.Write(bf, binary.LittleEndian, uint64(time.Now().Unix()))
+	bf.WriteByte(uint8(len(lg.appName)))
+	bf.WriteString(lg.appName)
+	_ = binary.Write(bf, binary.LittleEndian, uint16(len(ls)))
+	bf.WriteString(ls)
+	bf.WriteTo(lg.conn)
+}
+
+func NewLogHub(addr string) Logger {
+	var (
+		err     error
+		udpAddr *net.UDPAddr
+	)
+	if udpAddr, err = net.ResolveUDPAddr("udp", addr); err != nil {
+		return NewConsoleLogger()
+	}
+	hub := &LogHub{
+		appName: os.Getenv("MICRO_SERVICE_NAME"),
+	}
+	hub.conn, err = net.DialUDP("udp", nil, udpAddr)
+	return hub
+}