上卷 程序设计
中卷 标准库
- bufio 1.18
- bytes 1.18
- io 1.18
- container 1.18
- encoding 1.18
- crypto 1.18
- hash 1.18
- index 1.18
- sort 1.18
- context 1.18
- database 1.18
- connection
- query
- queryrow
- exec
- prepare
- transaction
- scan & null
- context
- tcp
- udp
- http
- server
- handler
- client
- h2、tls
- url
- rpc
- exec
- signal
- embed 1.18
- plugin 1.18
- reflect 1.18
- runtime 1.18
- KeepAlived
- ReadMemStats
- SetFinalizer
- Stack
- sync 1.18
- atomic
- mutex
- rwmutex
- waitgroup
- cond
- once
- map
- pool
- copycheck
- nocopy
- unsafe 1.18
- fmt 1.18
- log 1.18
- math 1.18
- time 1.18
- timer
下卷 运行时
源码剖析
附录
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
encoding 1.18
常用编码转换器。
base64
:基于 64 个可打印字符来表示二进制数据。binary
:转换数字和字节数组。(byte order)csv
:读写 CSV 表格文件。gob
:二进制序列化。hex
:十六进制编码。json
:JSON 编码。pem
:TLS 密钥和证书编码。(参考crypto/rsa
)xml
:XML 解析器。
base64
使用 NewEncoder
,记得调用 Close
。
package main import ( "bytes" "crypto/rand" "encoding/base64" "log" "fmt" ) func main() { d := make([]byte, 10) rand.Read(d) s := base64.StdEncoding.EncodeToString(d) b, _ := base64.StdEncoding.DecodeString(s) if !bytes.Equal(d, b) { log.Fatal() } fmt.Println(s) } // oLzIfNdzFRF7hA==
package main import ( "bytes" "encoding/base64" ) func main() { b := bytes.NewBuffer(nil) w := base64.NewEncoder(base64.StdEncoding, b) w.Write([]byte("1234")) w.Write([]byte("abc")) w.Close() // !!!! println(b.String()) // ------------------------------------------ r := base64.NewDecoder(base64.StdEncoding, b) bs := make([]byte, base64.StdEncoding.DecodedLen(b.Len())) r.Read(bs) println(string(bs)) } // MTIzNGFiYw== // 1234abc
binary
字节存储顺序(byte order)和处理器架构有关,如 Intel x86 是小端序。
- 大端(big endian):高位字节存放在低端地址。
- 小端(little endian):低位字节存放在低端地址。
注意,相关函数是否要求固定长度(fixed)类型。(如 int64
,非 int
)
package main import ( "bytes" "encoding/binary" "fmt" ) func main() { var x int64 = 0x11223344 big := bytes.NewBuffer(nil) binary.Write(big, binary.BigEndian, x) little := bytes.NewBuffer(nil) binary.Write(little, binary.LittleEndian, x) fmt.Printf("B: % x\n", big.Bytes()) fmt.Printf("L: % x\n", little.Bytes()) } // B: 00 00 00 00 11 22 33 44 // L: 44 33 22 11 00 00 00 00
判断当前系统大小端。
func main() { // 小端: [01, 00 ...] x := 1 p := (*byte)(unsafe.Pointer(&x)) println(*p == 1) }
csv
逗号分隔值(Comma-Separated Values),以纯文本格式存储表格数据(数字和文本)。
- 纯文本,使用某个字符集。比如 ASCII、Unicode、EBCDIC 或 GB2312。
- 由记录组成(典型的是每行一条记录)。
- 每条记录被分隔符分隔为字段(典型分隔符有逗号、分号或制表符)。
- 每条记录都有同样的字段序列。
双引号
用双引号( "
)表示包含空格的字段内容,其中可包含换行和分隔符。
两个连续双引号进行转义。
空白
空格等属于字段内容的组成部分。
空行被忽略,但由空白符填充的行不是空行。
字段可以没有内容,但记录必须有同等数量分隔符。
行末的换行回车符会被删除。
package main import ( "bytes" "encoding/csv" "fmt" "log" "strings" ) func main() { b := bytes.NewBuffer(nil) w := csv.NewWriter(b) w.Write([]string{"user1", "18", `data: "example"`}) w.Write([]string{"user2", "20", `data: "test xxx"`}) w.Flush() fmt.Println(b) // --------------------------------------------- r := csv.NewReader(b) recs, err := r.ReadAll() if err != nil { log.Fatalln(err) } for _, rec := range recs { fmt.Println(strings.Join(rec, " | ")) } } /* user1,18,"data: ""example""" user2,20,"data: ""test xxx""" user1 | 18 | data: "example" user2 | 20 | data: "test xxx" */
gob
自带二进制序列化方案。
- 性能好过
encoding/json
,但不如msgpack
、protocol buffer
。 - 可用来实现深拷贝(deep copy)。
- 因内部使用
reflect
实现,所以只处理导出字段。 - 编解码双方类型结构不要求完全一致,包括不同顺序。
- 忽略不匹配的字段,但最少有一个名字相同的字段。
- 支持值和指针转换,深度递归字段值。
package main import ( "bytes" "encoding/gob" "fmt" "log" ) func main() { a := struct { X int Y string z int16 // ignore }{ 100, "abc", 12, } b := struct { B bool Y *string X *int32 Z int16 }{} // ----------------------------------- data := bytes.NewBuffer(nil) enc := gob.NewEncoder(data) if err := enc.Encode(&a); err != nil { log.Fatalln(err) } fmt.Printf("% x\n", data.Bytes()) // ----------------------------------- dec := gob.NewDecoder(data) if err := dec.Decode(&b); err != nil { log.Fatalln(err) } fmt.Printf("%+v\n", b) fmt.Println(*b.X, *b.Y) } /* 18 ff 81 03 01 02 ff 82 00 ... 62 63 00 {B:false Y:0xc00008b590 X:0xc0000ae3b8 Z:0} 100 abc */
hex
十六进制字符串转换,中间不能有空格。
package main import ( "bytes" "encoding/hex" "fmt" "log" ) func main() { b := []byte{0x11, 0x22, 0x33} s := hex.EncodeToString(b) b2, err := hex.DecodeString(s) if err != nil { log.Fatalln(err) } if !bytes.Equal(b, b2) { log.Fatal() } fmt.Printf("%s\n% x\n", s, b2) } // 112233 // 11 22 33
比较有意思的是 Dump
,可以按习惯的十六进制编辑器方式输出。
func main() { b := []byte("hello, world!") fmt.Println(hex.Dump(b)) } /* 00000000 68 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21 |hello, world!| */
json
JSON 格式序列化转换。
- 递归对象字段结构,须是导出成员。
- 自动调用
MarshalJSON
、MarshalText
接口方法。 - 支持指针。
package main import ( "bytes" "encoding/json" "log" ) func main() { x := 100 d := struct { X *int S string Y []int }{ X: &x, S: "hello, world!", Y: []int{1, 2, 3, 4}, } // ----------------------- b, err := json.Marshal(d) if err != nil { log.Fatalln(err) } println(string(b)) // ----------------------- buf := bytes.NewBuffer(nil) json.Indent(buf, b, "", " ") println(buf.String()) } /* {"X":100,"S":"hello, world!","Y":[1,2,3,4]} { "X": 100, "S": "hello, world!", "Y": [ 1, 2, 3, 4 ] } */
标记
用 struct tag
标记 JSON 格式。
json:"[name|-],[omitempty|string]"
-
:忽略。omitempty
:空值时忽略。
package main import ( "bytes" "encoding/json" "log" ) func main() { x := 100 d := struct { X *int `json:"id"` S string `json:"name"` Y []byte `json:"data,omitempty"` }{ X: &x, S: "hello, <world!>", } // ----------------------- b, err := json.Marshal(d) if err != nil { log.Fatalln(err) } // ----------------------- buf := bytes.NewBuffer(nil) json.Indent(buf, b, "", " ") println(buf.String()) } /* { "id": 100, "name": "hello, \u003cworld!\u003e" } */
解码目标除结构体外,也可以是 map
(无需创建)。
- 忽略不存在的字段。
- 优先精确匹配字段名。找不到时,忽略大小写。
- 字段顺序不影响。
- 可为匿名字段添加
tag
标记。 - 字段名和匿名字段冲突,当前字段优先。
- 相同层次的多个匿名字段冲突,忽略冲突字段。
package main import ( "encoding/json" "log" "fmt" ) type U struct { Id int Name string } type M struct { U Title string } func main() { d := M { U{1, "user1"}, "cxo" } // ---------------------------- b, err := json.Marshal(d) if err != nil { log.Fatalln(err) } println(string(b)) // ---------------------------- // 相同类型。 func() { var x M if err := json.Unmarshal(b, &x); err != nil { log.Fatalln(err) } fmt.Printf("%+v\n", x) }() // ---------------------------- // 不同类型。 // ID 必须是导出成员,后续字母大小写可被忽略。 func() { var x struct { ID int Title string } if err := json.Unmarshal(b, &x); err != nil { log.Fatalln(err) } fmt.Printf("%+v\n", x) }() // ---------------------------- // 字典。 func() { var m map[string]interface{} if err := json.Unmarshal(b, &m); err != nil { log.Fatalln(err) } fmt.Printf("%v\n", m) }() } /* {"Id":1,"Name":"user1","Title":"cxo"} {U:{Id:1 Name:user1} Title:cxo} {ID:1 Title:cxo} map[Id:1 Name:user1 Title:cxo] */
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论