golang 序列化的庫沒其餘語言那麼好用,而後就掉坑裏了。git
是用gorequest 庫發現的,這個高start 的庫,仍是有些問題。我使用場景是這樣的:github
package main import ( "fmt" "github.com/parnurzeal/gorequest" ) type InStruct struct { Param float64 } func main() { postData := InStruct{Param: int64(72057594088097496)} resp, bodyBytes, errs := gorequest.New().Get("http://127.0.0.1:8080").Query(postData).EndBytes() fmt.Println(resp, bodyBytes, errs) }
而後,我發送的數據變成了:Param=72057594088097500。至關因而數據被四捨五入了,一番追查,發現底層作了這個操做,把數據給變了:golang
func (s *SuperAgent) queryStruct(content interface{}) *SuperAgent { if marshalContent, err := json.Marshal(content); err != nil { s.Errors = append(s.Errors, err) } else { var val map[string]interface{} if err := json.Unmarshal(marshalContent, &val); err != nil {// 這裏就會丟精度 s.Errors = append(s.Errors, err) } else { for k, v := range val { k = strings.ToLower(k) var queryVal string switch t := v.(type) { case string: queryVal = t case float64: queryVal = strconv.FormatFloat(t, 'f', -1, 64) case time.Time: queryVal = t.Format(time.RFC3339) default: j, err := json.Marshal(v) if err != nil { continue } queryVal = string(j) } s.QueryData.Add(k, queryVal) } } } return s }
換句話說,就是講數據由map[string]int64 變成map[string]interface{}, 而後,數據發生了變化。json
json 在處理go的數據類型轉換時,有個對應關係:數組
數據類型 | JSON | Golang |
---|---|---|
字串 | string | string |
整數 | number | int64 |
浮點數 | number | flaot64 |
數組 | arrary | slice |
對象 | object | struct |
布爾 | bool | bool |
空值 | null | nil |
在將數字類型unmarshal 轉化爲interface{} 的時候,默認會先使用浮點數轉換,這樣,可能會丟失精度。那如何處理?反序列化的時候,將數據類型轉換爲json.Number 就ok,這樣數據會延遲轉換,後面能夠根據須要轉換爲int64 或者是 float ,也能夠是string。app
給個正確的例子,應該使用UseNumber 反序列化:post
package main import ( "bytes" "encoding/json" "fmt" ) type Account struct { Email string `json:"email"` Password string `json:"password"` Money int64 `json:"money"` } func main() { account := Account{ Email: "137311107@qq.com", Password: "123", Money: int64(72057594088097496), } deal(account) } func deal(data interface{}) { bdata, err := json.Marshal(data) fmt.Printf("err %v, str %+v\n", err, string(bdata)) var val map[string]interface{} d := json.NewDecoder(bytes.NewBuffer(bdata)) d.UseNumber() err = d.Decode(&val) fmt.Printf("err %v, str %+v\n", err, val) }