背景:
初学golang,在demo项目中接入sms短信服务,需要通过第三方的接口校验验证码。
共使用到以下三个包:
"encoding/json" //json解析相关
"io/ioutil" //解析httpResponse的body
"net/http" //发起http请求
//校验收到的验证码
func VerifyCode(phone, code string) (bool, error) {
// json
contentType := "application/json"
data := mapToJSON(&map[string]interface{}{
"phone": phone,
"code": code,
"appkey": APP_KEY,
"zone": DEFAULT_ZONE,
})
resp, err := http.Post(VERIFY_URL, contentType, strings.NewReader(data))
if err != nil {
fmt.Printf("post failed, err:%v\n", err)
return false, err
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("get resp failed, err:%v\n", err)
return false, err
}
//json序列化成map 解析MOB验证接口的返回值
var tempMap map[string]interface{}
err = json.Unmarshal([]byte(b), &tempMap)
if err != nil {
fmt.Printf("parse resp failed, err:%v\n", err)
return false, err
}
//根据接口返回状态码 判断验证码结果
switch tempMap["status"] {
case 200:
return true, nil
case 405:
fmt.Println("code 405 int")
return true, nil
default:
return false,errors.New(tempMap["error"].(string))
}
}
出现的问题:
这里接入的是MOB的SMS服务,官方文档上给出的响应码应该就是整形的200、468等等三位的整型数。
而接口的返回值是json的形式
如{"status":200}、{"status":468,"error":"Illegal check request."}
上述代码里顺手就写了
case 200:
return true, nil
case 405:
fmt.Println("code 405 int")
return true, nil
default:
return false,errors.New(tempMap["error"].(string))
结果发现switch始终走的都是default分支,调试发现这里解析得到的status根本不是int型的,而是float64:
正是因此,switch没有进入200或者其他状态码的分支,于是可以对代码进行修改:
switch int(tempMap["status"].(float64))
先对map中value类型为interface{}的数据进行float64的断言,再通过强转变为int类型,于是能够正确地进入switch分支。
JSON解析数据的类型规则
JSON字符串,通过func Unmarshal(data []byte, v interface{})并将map[string]interface{}作第二个参数,可以解析成一个map。
在这种情况下,会按照以下规则解析value。
bool, for JSON booleans
float64, for JSON numbers //这就是本次问题产生的原因
string, for JSON strings
[]interface{}, for JSON arrays
map[string]interface{}, for JSON objects
nil for JSON null
版权声明:本文为qq_44336275原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。