context.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package cli
  2. import (
  3. "context"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "git.nspix.com/golang/micro/helper/utils"
  8. "reflect"
  9. "strconv"
  10. "strings"
  11. "sync"
  12. )
  13. var (
  14. ErrInvalidStruct = errors.New("invalid struct")
  15. ErrInvalidArgument = errors.New("invalid argument")
  16. )
  17. type encoder interface {
  18. Marshal() ([]byte, error)
  19. }
  20. type Context struct {
  21. ID int32
  22. CmdStr string
  23. Args []string //所有参数
  24. params []string
  25. locker sync.RWMutex
  26. Values map[string]interface{}
  27. response *Response
  28. ctx context.Context
  29. }
  30. func (ctx *Context) Context() context.Context {
  31. return ctx.ctx
  32. }
  33. func (ctx *Context) WithContext(c context.Context) {
  34. ctx.ctx = c
  35. }
  36. //HasArgument 是否有指定的参数
  37. func (ctx *Context) HasArgument(i int) bool {
  38. return len(ctx.Args) > i
  39. }
  40. //ParamValue 获取参数的值
  41. func (ctx *Context) ParamValue(name string) string {
  42. idx := -1
  43. if ctx.params == nil {
  44. return ""
  45. }
  46. for i, s := range ctx.params {
  47. if strings.ToLower(s) == strings.ToLower(name) {
  48. idx = i
  49. break
  50. }
  51. }
  52. if idx > -1 {
  53. if ctx.HasArgument(idx) {
  54. return ctx.Argument(idx)
  55. }
  56. }
  57. return ""
  58. }
  59. //Argument 获取指定参数
  60. func (ctx *Context) Argument(i int) string {
  61. if ctx.HasArgument(i) {
  62. return ctx.Args[i]
  63. }
  64. return ""
  65. }
  66. func (ctx *Context) reset(s string) {
  67. ctx.response = &Response{}
  68. ctx.Args = nil
  69. ctx.params = nil
  70. ctx.CmdStr = s
  71. }
  72. //Get 获取一个session变量
  73. func (ctx *Context) Get(s string) interface{} {
  74. ctx.locker.RLock()
  75. defer ctx.locker.RUnlock()
  76. if ctx.Values == nil {
  77. return ""
  78. }
  79. return ctx.Values[s]
  80. }
  81. //Set 设置一个session变量
  82. func (ctx *Context) Set(key string, value interface{}) {
  83. ctx.locker.Lock()
  84. defer ctx.locker.Unlock()
  85. if ctx.Values == nil {
  86. ctx.Values = make(map[string]interface{})
  87. }
  88. ctx.Values[key] = value
  89. }
  90. //Bind 绑定一个变量
  91. func (ctx *Context) Bind(i interface{}) (err error) {
  92. refVal := reflect.Indirect(reflect.ValueOf(i))
  93. refType := refVal.Type()
  94. if refVal.Kind() != reflect.Struct {
  95. return ErrInvalidStruct
  96. }
  97. numOfField := refVal.Type().NumField()
  98. if numOfField != len(ctx.Args) {
  99. var usage string
  100. usage = "Usage: " + ctx.CmdStr + " "
  101. for i := 0; i < numOfField; i++ {
  102. usage += "{" + utils.LowerFirst(refType.Field(i).Name) + "|" + refVal.Field(i).Type().Kind().String() + "} "
  103. }
  104. ctx.Set("usage", usage)
  105. return ErrInvalidArgument
  106. }
  107. for i := 0; i < numOfField; i++ {
  108. switch refVal.Field(i).Kind() {
  109. case reflect.String:
  110. refVal.Field(i).SetString(ctx.Args[i])
  111. case reflect.Int, reflect.Int32, reflect.Int64:
  112. n, _ := strconv.ParseInt(ctx.Args[i], 10, 64)
  113. refVal.Field(i).SetInt(n)
  114. case reflect.Float32, reflect.Float64:
  115. n, _ := strconv.ParseFloat(ctx.Args[i], 64)
  116. refVal.Field(i).SetFloat(n)
  117. default:
  118. err = fmt.Errorf("unsupported argument %d kind %s", i, refVal.Field(i).Kind())
  119. return
  120. }
  121. }
  122. return
  123. }
  124. func (ctx *Context) Error(code int, msg string) (err error) {
  125. ctx.response.Code = code
  126. ctx.response.Error = msg
  127. return
  128. }
  129. func (ctx *Context) Success(i interface{}) (err error) {
  130. if v, ok := i.(encoder); ok {
  131. ctx.response.Data, err = v.Marshal()
  132. return
  133. }
  134. refVal := reflect.Indirect(reflect.ValueOf(i))
  135. switch refVal.Kind() {
  136. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  137. ctx.response.Data = []byte(strconv.FormatInt(refVal.Int(), 10))
  138. case reflect.Float32, reflect.Float64:
  139. ctx.response.Data = []byte(strconv.FormatFloat(refVal.Float(), 'f', -1, 64))
  140. case reflect.String:
  141. ctx.response.Data = []byte(refVal.String())
  142. case reflect.Slice:
  143. if refVal.Type().Elem().Kind() == reflect.Uint8 {
  144. ctx.response.Data = refVal.Bytes()
  145. } else {
  146. ctx.response.Data, err = json.MarshalIndent(refVal.Interface(), "", "\t")
  147. }
  148. case reflect.Struct, reflect.Map:
  149. ctx.response.Data, err = json.MarshalIndent(refVal.Interface(), "", "\t")
  150. default:
  151. ctx.response.Data, err = json.MarshalIndent(refVal.Interface(), "", "\t")
  152. }
  153. return
  154. }