golang学习笔记:标准库encoding
在Go语言中,encoding包及其子包是用来处理不同编码格式的。
常用子包
encoding/json - JSON编码解码
基本编码解码
import "encoding/json"type User struct {Name string `json:"name"`Age int `json:"age,omitempty"`Email string `json:"email,omitempty"`
}// 编码(序列化)
user := User{Name: "Alice", Age: 25}
data, err := json.Marshal(user) // {"name":"Alice","age":25}
data, err = json.MarshalIndent(user, "", " ") // 格式化输出// 解码(反序列化)
var decodedUser User
err = json.Unmarshal(data, &decodedUser)
流式处理
// 编码到 Writer
err := json.NewEncoder(file).Encode(user)// 从 Reader 解码
err := json.NewDecoder(file).Decode(&user)
自定义编码
type CustomTime time.Timefunc (ct *CustomTime) MarshalJSON() ([]byte, error) {return json.Marshal(time.Time(*ct).Format("2006-01-02"))
}func (ct *CustomTime) UnmarshalJSON(data []byte) error {var str stringif err := json.Unmarshal(data, &str); err != nil {return err}t, err := time.Parse("2006-01-02", str)if err != nil {return err}*ct = CustomTime(t)return nil
}
原始消息处理
type Response struct {Status int `json:"status"`Data json.RawMessage `json:"data"` // 延迟解析
}var resp Response
json.Unmarshal(data, &resp)// 根据类型解析 Data
if resp.Status == 200 {var user Userjson.Unmarshal(resp.Data, &user)
} else {var errorMsg map[string]stringjson.Unmarshal(resp.Data, &errorMsg)
}
encoding/xml - XML编码解码
基本XML处理
import "encoding/xml"type Book struct {XMLName xml.Name `xml:"book"`Title string `xml:"title"`Author string `xml:"author"`Year int `xml:"year,attr"`Price float64 `xml:"price"`
}// 编码
book := Book{Title: "Go Programming", Author: "Alice", Year: 2023}
data, err := xml.Marshal(book)
data, err = xml.MarshalIndent(book, "", " ")// 解码
var decodedBook Book
err = xml.Unmarshal(data, &decodedBook)
XML 特性
type Catalog struct {XMLName xml.Name `xml:"catalog"`Books []Book `xml:"book"`Comment string `xml:",comment"` // 注释ID string `xml:"id,attr"` // 属性Data string `xml:",chardata"` // 字符数据Inner string `xml:",innerxml"` // 原始 XMLOmit string `xml:",omitempty"` // 空值忽略
}
流式处理
// 编码到 Writer
err := xml.NewEncoder(file).Encode(catalog)// 从 Reader 解码
err := xml.NewDecoder(file).Decode(&catalog)
encoding/base64 - Base64编码
标准Base64
import "encoding/base64"data := []byte("hello world")// 编码
encoded := base64.StdEncoding.EncodeToString(data)
// "aGVsbG8gd29ybGQ="// 解码
decoded, err := base64.StdEncoding.DecodeString(encoded)
URL安全的Base64
// URL 和文件名安全编码
urlEncoded := base64.URLEncoding.EncodeToString(data)
// "aGVsbG8gd29ybGQ="// 原始标准编码(无填充)
rawEncoded := base64.RawStdEncoding.EncodeToString(data)
自定义编码
// 自定义编码器
customEncoding := base64.NewEncoding("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
encoded := customEncoding.EncodeToString(data)
encoding/hex - 十六进制编码
基本十六进制转换
import "encoding/hex"data := []byte("Hello")// 编码为十六进制字符串
encoded := hex.EncodeToString(data)
// "48656c6c6f"// 解码十六进制字符串
decoded, err := hex.DecodeString(encoded)
格式化输出
// 带空格的分隔格式
src := []byte{0x48, 0x65, 0x6c, 0x6c, 0x6f}
dst := make([]byte, hex.EncodedLen(len(src)))
hex.Encode(dst, src)
// "48656c6c6f"// 解码到字节切片
srcStr := "48 65 6c 6c 6f"
dst := make([]byte, hex.DecodedLen(len(srcStr)))
_, err := hex.Decode(dst, []byte(srcStr))
encoding/csv - CSV文件处理
读取 CSV
import "encoding/csv"// 从字符串读取
csvData := `name,age,city
Alice,30,New York
Bob,25,London`reader := csv.NewReader(strings.NewReader(csvData))
records, err := reader.ReadAll()
// [["name" "age" "city"] ["Alice" "30" "New York"] ["Bob" "25" "London"]]// 逐行读取
reader = csv.NewReader(file)
for {record, err := reader.Read()if err == io.EOF {break}if err != nil {log.Fatal(err)}// 处理 record
}
写入CSV
// 写入到 Writer
var buf bytes.Buffer
writer := csv.NewWriter(&buf)records := [][]string{{"name", "age", "city"},{"Alice", "30", "New York"},{"Bob", "25", "London"},
}err := writer.WriteAll(records)
writer.Flush() // 确保数据写入
CSV配置
reader := csv.NewReader(file)
reader.Comma = ';' // 自定义分隔符
reader.Comment = '#' // 注释字符
reader.FieldsPerRecord = 3 // 每行字段数
reader.TrimLeadingSpace = true // 修剪前导空格writer := csv.NewWriter(file)
writer.UseCRLF = true // 使用 Windows 换行符
encoding/gob - Go二进制编码
基本使用
import "encoding/gob"type Person struct {Name stringAge int
}// 编码
var network bytes.Buffer
person := Person{Name: "Alice", Age: 30}
encoder := gob.NewEncoder(&network)
err := encoder.Encode(person)// 解码
var decodedPerson Person
decoder := gob.NewDecoder(&network)
err = decoder.Decode(&decodedPerson)
注册类型
// 注册自定义类型
gob.Register(Person{})// 编码接口类型
var buffer bytes.Buffer
encoder := gob.NewEncoder(&buffer)var data interface{} = Person{Name: "Bob", Age: 25}
err := encoder.Encode(&data)
使用示例
配置管理
package configimport ("encoding/json""os"
)type Config struct {Database DatabaseConfig `json:"database"`Server ServerConfig `json:"server"`Features []string `json:"features"`
}type DatabaseConfig struct {Host string `json:"host"`Port int `json:"port"`Username string `json:"username"`Password string `json:"password"`
}type ServerConfig struct {Port int `json:"port"`Timeout int `json:"timeout"`Env string `json:"env"`
}func LoadConfig(path string) (*Config, error) {file, err := os.Open(path)if err != nil {return nil, err}defer file.Close()var config Configdecoder := json.NewDecoder(file)if err := decoder.Decode(&config); err != nil {return nil, err}return &config, nil
}func SaveConfig(config *Config, path string) error {file, err := os.Create(path)if err != nil {return err}defer file.Close()encoder := json.NewEncoder(file)encoder.SetIndent("", " ")return encoder.Encode(config)
}
API 响应处理
package apiimport ("encoding/json""net/http"
)type Response struct {Success bool `json:"success"`Data interface{} `json:"data,omitempty"`Error string `json:"error,omitempty"`Code int `json:"code,omitempty"`
}func WriteJSON(w http.ResponseWriter, status int, data interface{}) error {w.Header().Set("Content-Type", "application/json")w.WriteHeader(status)return json.NewEncoder(w).Encode(data)
}func WriteSuccess(w http.ResponseWriter, data interface{}) error {resp := Response{Success: true, Data: data}return WriteJSON(w, http.StatusOK, resp)
}func WriteError(w http.ResponseWriter, status int, errMsg string) error {resp := Response{Success: false, Error: errMsg, Code: status}return WriteJSON(w, status, resp)
}func ReadJSON(r *http.Request, v interface{}) error {return json.NewDecoder(r.Body).Decode(v)
}
数据加密存储
package storageimport ("encoding/base64""encoding/json""crypto/aes""crypto/cipher"
)type SecureStorage struct {key []byte
}func NewSecureStorage(key string) *SecureStorage {// 确保密钥长度合适keyBytes := make([]byte, 32)copy(keyBytes, []byte(key))return &SecureStorage{key: keyBytes}
}func (s *SecureStorage) EncryptAndStore(data interface{}) (string, error) {// 序列化为 JSONjsonData, err := json.Marshal(data)if err != nil {return "", err}// 加密block, err := aes.NewCipher(s.key)if err != nil {return "", err}gcm, err := cipher.NewGCM(block)if err != nil {return "", err}nonce := make([]byte, gcm.NonceSize())encrypted := gcm.Seal(nonce, nonce, jsonData, nil)// Base64 编码return base64.URLEncoding.EncodeToString(encrypted), nil
}func (s *SecureStorage) DecryptAndLoad(encryptedStr string, v interface{}) error {// Base64 解码encrypted, err := base64.URLEncoding.DecodeString(encryptedStr)if err != nil {return err}// 解密block, err := aes.NewCipher(s.key)if err != nil {return err}gcm, err := cipher.NewGCM(block)if err != nil {return err}nonceSize := gcm.NonceSize()nonce, ciphertext := encrypted[:nonceSize], encrypted[nonceSize:]jsonData, err := gcm.Open(nil, nonce, ciphertext, nil)if err != nil {return err}// 反序列化return json.Unmarshal(jsonData, v)
}
消息序列化系统
package messagingimport ("encoding/gob""encoding/json""encoding/xml""bytes""fmt"
)type Message struct {Type string `json:"type" xml:"type"`Payload interface{} `json:"payload" xml:"payload"`
}type Serializer interface {Serialize(interface{}) ([]byte, error)Deserialize([]byte, interface{}) error
}type JSONSerializer struct{}func (j JSONSerializer) Serialize(v interface{}) ([]byte, error) {return json.Marshal(v)
}func (j JSONSerializer) Deserialize(data []byte, v interface{}) error {return json.Unmarshal(data, v)
}type XMLSerializer struct{}func (x XMLSerializer) Serialize(v interface{}) ([]byte, error) {return xml.Marshal(v)
}func (x XMLSerializer) Deserialize(data []byte, v interface{}) error {return xml.Unmarshal(data, v)
}type GobsSerializer struct{}func (g GobsSerializer) Serialize(v interface{}) ([]byte, error) {var buf bytes.Bufferencoder := gob.NewEncoder(&buf)if err := encoder.Encode(v); err != nil {return nil, err}return buf.Bytes(), nil
}func (g GobsSerializer) Deserialize(data []byte, v interface{}) error {buf := bytes.NewBuffer(data)decoder := gob.NewDecoder(buf)return decoder.Decode(v)
}type MessageBus struct {serializer Serializer
}func NewMessageBus(serializer Serializer) *MessageBus {return &MessageBus{serializer: serializer}
}func (m *MessageBus) Send(message Message) ([]byte, error) {return m.serializer.Serialize(message)
}func (m *MessageBus) Receive(data []byte) (*Message, error) {var message Messageif err := m.serializer.Deserialize(data, &message); err != nil {return nil, err}return &message, nil
}
性能优化技巧
1.重用编码器/解码器
// 不推荐:每次创建新的编码器
func process(data interface{}) ([]byte, error) {return json.Marshal(data)
}// 推荐:重用编码器
var encoderBuffer bytes.Buffer
var encoder = json.NewEncoder(&encoderBuffer)func processOptimized(data interface{}) ([]byte, error) {encoderBuffer.Reset()if err := encoder.Encode(data); err != nil {return nil, err}return encoderBuffer.Bytes(), nil
}
2.预分配缓冲区
func encodeLargeData(data []interface{}) ([]byte, error) {var buf bytes.Bufferbuf.Grow(1024 * 1024) // 预分配 1MBencoder := json.NewEncoder(&buf)if err := encoder.Encode(data); err != nil {return nil, err}return buf.Bytes(), nil
}
