1.打印相关
package main
import (
"fmt"
)
func main() {
fmt.Print("输出到控制台不换行")
fmt.Println("---")
fmt.Println("输出到控制台并换行")
fmt.Printf("name=%s,age=%d\n", "Tom", 30)
fmt.Printf("name=%s,age=%d,height=%v\n", "Tom", 30, fmt.Sprintf("%.2f", 180.567))
}
2.切片相关
package main
import (
"fmt"
)
func main() {
sli := [] int {1, 2, 3, 4, 5, 6}
fmt.Printf("len=%d cap=%d slice=%v\n",len(sli),cap(sli),sli)
fmt.Println("sli[1] ==", sli[1])
fmt.Println("sli[:] ==", sli[:])
fmt.Println("sli[1:] ==", sli[1:])
fmt.Println("sli[:4] ==", sli[:4])
fmt.Println("sli[0:3] ==", sli[0:3])
fmt.Printf("len=%d cap=%d slice=%v\n",len(sli[0:3]),cap(sli[0:3]),sli[0:3])
fmt.Println("sli[0:3:4] ==", sli[0:3:4])
fmt.Printf("len=%d cap=%d slice=%v\n",len(sli[0:3:4]),cap(sli[0:3:4]),sli[0:3:4])
fmt.Printf("len=%d cap=%d slice=%v\n",len(sli),cap(sli),sli)
sli = append(sli, 7)
fmt.Printf("len=%d cap=%d slice=%v\n",len(sli),cap(sli),sli)
sli = append(sli, 8)
fmt.Printf("len=%d cap=%d slice=%v\n",len(sli),cap(sli),sli)
sli = append(sli, 9)
fmt.Printf("len=%d cap=%d slice=%v\n",len(sli),cap(sli),sli)
sli = append(sli, 10)
fmt.Printf("len=%d cap=%d slice=%v\n",len(sli),cap(sli),sli)
fmt.Printf("len=%d cap=%d slice=%v\n",len(sli),cap(sli),sli)
//删除尾部 2 个元素
fmt.Printf("len=%d cap=%d slice=%v\n",len(sli[:len(sli)-2]),cap(sli[:len(sli)-2]),sli[:len(sli)-2])
//删除开头 2 个元素
fmt.Printf("len=%d cap=%d slice=%v\n",len(sli[2:]),cap(sli[2:]),sli[2:])
//删除中间 2 个元素
sli = append(sli[:3], sli[3+2:]...)
fmt.Printf("len=%d cap=%d slice=%v\n",len(sli),cap(sli),sli)
}
3.结构体相关
package main
import (
"fmt"
)
type Person struct {
Name string
Age int
}
func main() {
var p1 Person
p1.Name = "Tom"
p1.Age = 30
fmt.Println("p1 =", p1)
var p2 = Person{Name:"Burke", Age:31}
fmt.Println("p2 =", p2)
p3 := Person{Name:"Aaron", Age:32}
fmt.Println("p2 =", p3)
//匿名结构体
p4 := struct {
Name string
Age int
} {Name:"匿名", Age:33}
fmt.Println("p4 =", p4)
}
4.结构体数据序列化和反序列化
package main
import (
"encoding/json"
"fmt"
)
type Result1 struct {
Code int `json:"code"`
Message string `json:"msg"`
}
func main() {
var res Result1
res.Code = 200
res.Message = "success"
//序列化
jsons, errs := json.Marshal(res)
if errs != nil {
fmt.Println("json marshal error:", errs)
}
fmt.Println("json data :", string(jsons))
//反序列化
var res2 Result1
errs = json.Unmarshal(jsons, &res2)
if errs != nil {
fmt.Println("json unmarshal error:", errs)
}
fmt.Println("res2 :", res2)
}
5.结构体为值传递,结构体的重新赋值,通过指针处理
package main
import (
"encoding/json"
"fmt"
)
type Result struct {
Code int `json:"code"`
Message string `json:"msg"`
}
func main() {
var res Result
res.Code = 200
res.Message = "success"
toJson(&res)
setData(&res)
toJson(&res)
}
func setData (res *Result) {
res.Code = 500
res.Message = "fail"
}
func toJson (res *Result) {
jsons, errs := json.Marshal(res)
if errs != nil {
fmt.Println("json marshal error:", errs)
}
fmt.Println("json data :", string(jsons))
}
6.map的多种定义和使用
//demo_14.go
package main
import (
"fmt"
)
func main() {
var p1 map[int]string
p1 = make(map[int]string)
p1[1] = "Tom"
fmt.Println("p1 :", p1)
var p2 map[int]string = map[int]string{}
p2[1] = "Tom"
fmt.Println("p2 :", p2)
var p3 map[int]string = make(map[int]string)
p3[1] = "Tom"
fmt.Println("p3 :", p3)
p4 := map[int]string{}
p4[1] = "Tom"
fmt.Println("p4 :", p4)
p5 := make(map[int]string)
p5[1] = "Tom"
fmt.Println("p5 :", p5)
p6 := map[int]string{
1 : "Tom",
}
fmt.Println("p6 :", p6)
}
7.map数据的序列化与反序列化
//demo_15.go
package main
import (
"encoding/json"
"fmt"
)
func main() {
res := make(map[string]interface{})
res["code"] = 200
res["msg"] = "success"
res["data"] = map[string]interface{}{
"username" : "Tom",
"age" : "30",
"hobby" : []string{"读书","爬山"},
}
fmt.Println("map data :", res)
//序列化
jsons, errs := json.Marshal(res)
if errs != nil {
fmt.Println("json marshal error:", errs)
}
fmt.Println("")
fmt.Println("--- map to json ---")
fmt.Println("json data :", string(jsons))
//反序列化
res2 := make(map[string]interface{})
errs = json.Unmarshal([]byte(jsons), &res2)
if errs != nil {
fmt.Println("json marshal error:", errs)
}
fmt.Println("")
fmt.Println("--- json to map ---")
fmt.Println("map data :", res2)
}
8.生成签名
//demo_26.go
package main
import (
"crypto/md5"
"encoding/hex"
"fmt"
"sort"
"time"
)
func main() {
str := "12345"
fmt.Printf("MD5(%s): %s\n", str, MD5(str))
fmt.Printf("current time str : %s\n", getTimeStr())
fmt.Printf("current time unix : %d\n", getTimeInt())
params := map[string]interface{} {
"name" : "Tom",
"pwd" : "123456",
"age" : 30,
}
fmt.Printf("sign : %s\n", createSign(params))
}
// MD5 方法
func MD5(str string) string {
s := md5.New()
s.Write([]byte(str))
return hex.EncodeToString(s.Sum(nil))
}
// 获取当前时间字符串
func getTimeStr() string {
return time.Now().Format("2006-01-02 15:04:05")
}
// 获取当前时间戳
func getTimeInt() int64 {
return time.Now().Unix()
}
// 生成签名
func createSign(params map[string]interface{}) string {
var key []string
var str = ""
for k := range params {
key = append(key, k)
}
sort.Strings(key)
for i := 0; i < len(key); i++ {
if i == 0 {
str = fmt.Sprintf("%v=%v", key[i], params[key[i]])
} else {
str = str + fmt.Sprintf("&xl_%v=%v", key[i], params[key[i]])
}
}
// 自定义密钥
var secret = "123456789"
// 自定义签名算法
sign := MD5(MD5(str) + MD5(secret))
return sign
}
9.json.Unmarshal 遇到的小坑
1.问题现象描述
使用 json.Unmarshal()
,反序列化时,出现了科学计数法,参考代码如下:
jsonStr := `{"number":1234567}`
result := make(map[string]interface{})
err := json.Unmarshal([]byte(jsonStr), &result)
if err != nil {
fmt.Println(err)
}
fmt.Println(result)
// 输出
// map[number:1.234567e+06]
这个问题不是必现,只有当数字的位数大于 6 位时,才会变成了科学计数法。
2.问题影响描述
当数据结构未知,使用 map[string]interface{}
来接收反序列化结果时,如果数字的位数大于 6 位,都会变成科学计数法,用到的地方都会受到影响。
3.引起问题的原因
从 encoding/json
可以找到答案,看一下这段注释:
// To unmarshal JSON into an interface value,
// Unmarshal stores one of these in the interface 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
是因为当 JSON
中存在一个比较大的数字时,它会被解析成 float64
类型,就有可能会出现科学计数法的形式。
4.问题的解决方案
方案一
强制类型转换,参考代码如下:
jsonStr := `{"number":1234567}`
result := make(map[string]interface{})
err := json.Unmarshal([]byte(jsonStr), &result)
if err != nil {
fmt.Println(err)
}
fmt.Println(int(result["number"].(float64)))
// 输出
// 1234567
方案二
尽量避免使用 interface
,对 json
字符串结构定义结构体,快捷方法可使用在线工具:https://mholt.github.io/json-to-go/
。
type Num struct {
Number int `json:"number"`
}
jsonStr := `{"number":1234567}`
var result Num
err := json.Unmarshal([]byte(jsonStr), &result)
if err != nil {
fmt.Println(err)
}
fmt.Println(result)
// 输出
// {1234567}
方案三
使用 UseNumber()
方法。
jsonStr := `{"number":1234567}`
result := make(map[string]interface{})
d := json.NewDecoder(bytes.NewReader([]byte(jsonStr)))
d.UseNumber()
err := d.Decode(&result)
if err != nil {
fmt.Println(err)
}
fmt.Println(result)
// 输出
// map[number:1234567]
这时一定要注意 result["number"]
的数据类型!
fmt.Println(fmt.Sprintf("type: %v", reflect.TypeOf(result["number"])))
// 输出
// type: json.Number
通过代码可以看出 json.Number
其实就是字符串类型:
// A Number represents a JSON number literal.
type Number string
如果转换其他类型,参考如下代码:
// 转成 int64
numInt, _ := result["number"].(json.Number).Int64()
fmt.Println(fmt.Sprintf("value: %v, type: %v", numInt, reflect.TypeOf(numInt)))
// 输出
// value: 1234567, type: int64
// 转成 string
numStr := result["number"].(json.Number).String()
fmt.Println(fmt.Sprintf("value: %v, type: %v", numStr, reflect.TypeOf(numStr)))
// 输出
// value: 1234567, type: string