context.go 3.4 KB

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