偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Go JSON v2 來了?。?!

開發(fā) 前端
從目前的設(shè)計(jì)來看,JSON v2 確實(shí)解決了現(xiàn)有 ??encoding/json?? 包的很多痛點(diǎn):性能大幅提升、API 更加靈活、支持更多自定義選項(xiàng)。雖然學(xué)習(xí)成本有一定增加,但是帶來的收益是值得的。

說實(shí)話,現(xiàn)有的 encoding/json 包雖然能用,但是各種限制和性能問題確實(shí)讓人頭疼,特別是處理大量數(shù)據(jù)的時(shí)候,那速度真的是...很容易擺爛。

新版本 Go1.25 有一個(gè)很多 Gopher 期待已久的新標(biāo)準(zhǔn)庫——JSON v2[1](實(shí)驗(yàn)階段),能夠較好的解決這個(gè)煩惱。

圖片圖片

為什么需要 JSON v2?

第一:現(xiàn)有的 encoding/json 包確實(shí)有不少歷史包袱。從 Go 1.0 到現(xiàn)在,這個(gè)包基本沒怎么大改過,很多設(shè)計(jì)上的問題一直拖著。比如說:

  • Encoder/Decoder 的 API 設(shè)計(jì)不夠靈活。
  • 自定義序列化的方式太單一。
  • 性能問題,特別是反序列化的性能。
  • 一些默認(rèn)行為不太合理。

第二:社區(qū)呼聲很高。你去看看 GitHub 上的 issue,關(guān)于 JSON 包的吐槽那是一抓一大把。大家都希望有個(gè)更好用、更快的 JSON 包。

但很無奈的是,Go 的兼容性承諾在那擺著,不能隨便改現(xiàn)有的 API。

所以 Go 團(tuán)隊(duì)這次的思路是:搞個(gè) v2,先用 GOEXPERIMENT 來控制。

JSON v2 到底改了啥?

接下來我們看下 JSON v2 的核心變化。這個(gè)新版本不是簡單的修修補(bǔ)補(bǔ)。

是從 API 設(shè)計(jì)到內(nèi)部實(shí)現(xiàn)的全面重構(gòu)。所以搞了很久才釋出。

新的 API 設(shè)計(jì)

最明顯的變化就是 API:

圖片圖片

以下是一些要點(diǎn)介紹。

更直觀的 IO 操作

原來我們要寫入 io.Writer 或者從 io.Reader 讀取,得用 Encoder 和 Decoder

// v1 的寫法
alice := Person{Name: "Alice", Age: 25}
out := new(strings.Builder)
enc := json.NewEncoder(out)
enc.Encode(alice)
fmt.Println(out.String())

現(xiàn)在 v2 直接提供了 MarshalWrite 和 UnmarshalRead

// v2 的寫法
alice := Person{Name: "Alice", Age: 25}
out := new(strings.Builder)
json.MarshalWrite(out, alice)
fmt.Println(out.String())

簡單來說,就是少了一層中間商賺差價(jià)。

不過這里有幾個(gè)點(diǎn)需要注意:

  • MarshalWrite 不會添加換行符,而老的 Encoder.Encode 會。
  • UnmarshalRead 會讀取整個(gè) reader 直到 EOF,而老的 Decoder.Decode 只讀下一個(gè) JSON 值。

如果你需要流式處理,v2 也提供了新的方案。Encoder 和 Decoder 被移到了 jsontext 包,配合 MarshalEncode 和 UnmarshalDecode 使用:

// 流式編碼
people := []Person{
    {Name: "Alice", Age: 25},
    {Name: "Bob", Age: 30},
}
out := new(strings.Builder)
enc := jsontext.NewEncoder(out)

for _, p := range people {
    json.MarshalEncode(enc, p)
}

強(qiáng)大的配置選項(xiàng)

這個(gè)真的是 v2 的一大亮點(diǎn)。再也不用為了改個(gè)格式而頭疼了。

alice := Person{Name: "Alice", Age: 25}
b, _ := json.Marshal(
    alice,
    json.OmitZeroStructFields(true),  // 省略零值字段
    json.StringifyNumbers(true),      // 數(shù)字轉(zhuǎn)字符串
    jsontext.WithIndent("  "),       // 縮進(jìn)格式化
)
fmt.Println(string(b))

還可以用 JoinOptions 組合選項(xiàng):

opts := json.JoinOptions(
    jsontext.SpaceAfterColon(true),
    jsontext.SpaceAfterComma(true),
)
b, _ := json.Marshal(alice, opts)

增強(qiáng)的標(biāo)簽支持

v2 不僅支持原有的標(biāo)簽,還新增了幾個(gè)很實(shí)用的:

type Person struct {
    Name      string    `json:"name"`
    BirthDate time.Time `json:"birth_date,format:DateOnly"` // 格式化日期
    Address             `json:",inline"`                    // 內(nèi)聯(lián)字段
}

type Address struct {
    Street string `json:"street"`
    City   string `json:"city"`
}

inline 標(biāo)簽可以把嵌套對象的字段提升到父對象:

alice := Person{
    Name: "Alice",
    BirthDate: time.Date(2001, 7, 15, 12, 35, 43, 0, time.UTC),
    Address: Address{
        Street: "123 Main St",
        City:   "Wonderland",
    },
}
// 輸出會把 street 和 city 直接放在 Person 對象里

還有個(gè) unknown 標(biāo)簽,可以收集所有未知字段:

type Person struct {
    Name string         `json:"name"`
    Data map[string]any `json:",unknown"` // 收集未知字段
}

靈活的自定義序列化

這個(gè)功能真的讓我眼前一亮。以前要自定義序列化,必須給類型實(shí)現(xiàn) MarshalJSON 方法。

現(xiàn)在你可以用 MarshalFunc 隨時(shí)定義:

// 把 bool 序列化成 ? 或 ?
boolMarshaler := json.MarshalFunc(
    func(val bool) ([]byte, error) {
        if val {
            return []byte(`"?"`), nil
        }
        return []byte(`"?"`), nil
    },
)

val := true
data, err := json.Marshal(val, json.WithMarshalers(boolMarshaler))
fmt.Println(string(data)) // "?"

還可以組合多個(gè)自定義序列化器:

// 可以同時(shí)處理 bool 和 bool-like 字符串
strMarshaler := json.MarshalToFunc(
    func(enc *jsontext.Encoder, val string) error {
        if val == "on" || val == "true" {
            return enc.WriteToken(jsontext.String("?"))
        }
        if val == "off" || val == "false" {
            return enc.WriteToken(jsontext.String("?"))
        }
        return json.SkipFunc // 跳過,使用默認(rèn)序列化
    },
)

marshalers := json.JoinMarshalers(boolMarshaler, strMarshaler)

默認(rèn)行為的改進(jìn)

v2 修正了一些反直覺的默認(rèn)行為:

  • nil slice 現(xiàn)在序列化成 [] 而不是 null。
  • nil map 現(xiàn)在序列化成 {} 而不是 null。
  • 字節(jié)數(shù)組默認(rèn)編碼為 base64 字符串,而不是數(shù)字?jǐn)?shù)組。
  • 字段名匹配默認(rèn)區(qū)分大小寫。

例子如下:

type Person struct {
    Name    string
    Hobbies []string
    Skills  map[string]int
    Secret  [5]byte
}

alice := Person{
    Name:   "Alice",
    Secret: [5]byte{1, 2, 3, 4, 5},
}
// v2 輸出:
// {
//   "Name": "Alice",
//   "Hobbies": [],
//   "Skills": {},
//   "Secret": "AQIDBAU="
// }

如果想要 v1 的行為,可以通過選項(xiàng)配置:

b, _ := json.Marshal(
    alice,
    json.FormatNilMapAsNull(true),
    json.FormatNilSliceAsNull(true),
)

JSON v2 性能大幅提高

目前看來,根據(jù)官方的 benchmark[2] 數(shù)據(jù),反序列化性能提升了 2.7 到 10.2 倍,這個(gè)提升幅度確實(shí)很可觀。

圖片圖片

特別是對于那些需要處理大量 JSON 數(shù)據(jù)的項(xiàng)目,比如微服務(wù)之間的通信、日志處理等場景,這個(gè)性能提升是實(shí)打?qū)嵉摹?/span>

如何嘗鮮?

我們來看下怎么體驗(yàn) JSON v2。目前 JSON v2 還在實(shí)驗(yàn)階段。

圖片圖片

需要設(shè)置環(huán)境變量開啟:

GOEXPERIMENT=jsonv2 go build your_project

當(dāng)設(shè)置了這個(gè)標(biāo)志后:

  • 新的 encoding/json/v2 和 encoding/json/jsontext 包會生效。
  • 現(xiàn)有的 encoding/json 包會使用 v2 的實(shí)現(xiàn)。
  • 可以使用 v2 提案中的新 API。

總結(jié)

從目前的設(shè)計(jì)來看,JSON v2 確實(shí)解決了現(xiàn)有 encoding/json 包的很多痛點(diǎn):性能大幅提升、API 更加靈活、支持更多自定義選項(xiàng)。雖然學(xué)習(xí)成本有一定增加,但是帶來的收益是值得的。

如果能在后續(xù)版本轉(zhuǎn)正(正式落地),相信會讓很多 Gopher 的開發(fā)體驗(yàn)有質(zhì)的提升。畢竟誰不想告別那些繁瑣的 JSON 處理代碼呢?

參考資料

[1] JSON v2: https://github.com/golang/go/issues/71845

[2] benchmark: https://github.com/go-json-experiment/jsonbench

責(zé)任編輯:武曉燕 來源: 腦子進(jìn)煎魚了
相關(guān)推薦

2024-05-10 08:47:22

標(biāo)準(zhǔn)庫v2Go

2010-08-05 17:00:04

RIP V2協(xié)議

2010-08-06 14:07:21

RIP V2

2025-03-06 08:54:24

泛型類型MapGo1

2023-01-09 12:41:55

模型

2021-08-18 10:39:13

Ubuntu 21.1Linux 內(nèi)核開發(fā)人員

2023-02-03 09:10:32

大數(shù)據(jù)SeaTunnel

2013-04-13 13:49:35

組播IGMP V2包

2012-04-24 18:10:56

華為E5

2023-06-20 08:01:09

RoseDB存儲數(shù)據(jù)

2021-06-05 10:16:55

Linkerd 服務(wù)網(wǎng)格Kubernetes

2023-07-18 14:50:15

2009-10-12 08:21:09

ExadataOracleOPN

2025-05-20 08:00:00

Go語言Gin

2022-12-14 10:21:25

目標(biāo)檢測框架

2022-12-14 08:58:48

谷歌Chrome瀏覽器

2009-08-28 11:30:36

GPL v2授權(quán)

2021-09-27 09:55:06

Chrome瀏覽器Manifest V2

2013-01-08 17:30:31

Google MapsAndroid MapMapFragment

2013-09-18 13:51:00

華為服務(wù)器華為
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號