context.go 3.5 KB

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