You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go中ASN1编解码时asn1:"-"标签为何不生效?

问题:Go标准库encoding/asn1中asn1:"-"标签为何无法像json:"-"那样忽略结构体字段?

以下代码尝试对bearer结构体执行ASN.1编组:

type bearer struct {
    CreatedAt time.Time     `asn1:"generalized"`
    ExpiresAt time.Time     `asn1:"generalized"`
    Nonce     string
    Signature []byte        `asn1:"-"`
    TTL       time.Duration `asn1:"-"`
    Frequency int           `asn1:"-"`
}

c := &bearer{
  CreatedAt: time.Now()
  ExpiresAt: time.Now().Add(1*time.Minute())
  Nonce: "123456789abcdefghijklmnop"
  Frequency: 1
}

b, err := asn1.Marshal(*c)
os.WriteFile("b64.txt", b, 0777)

执行后通过Bash命令base64 -d b64.txt > b64.txt.der检查发现,标记为asn1:"-"的字段仍被编入结果,无值字段还出现“Error: Object has zero length.”错误。


原因分析

Go标准库encoding/asn1与encoding/json的标签逻辑完全不同:

  • json:"-"的作用是直接忽略字段,但asn1:"-"的功能是禁用字段的默认ASN.1标签编号,让字段使用上下文自动分配的编号,并不会跳过字段的编组流程。
  • encoding/asn1的编组规则仅会跳过未导出字段(首字母小写),而导出字段无论是否标记-"标签,只要有值(或零值未触发omitempty)都会被处理。

解决方案

要彻底忽略指定字段,有两种可靠方式:

方式一:改为未导出字段

将不需要编组的字段首字母改为小写,ASN.1编组会自动跳过这些未导出字段:

type bearer struct {
    CreatedAt time.Time     `asn1:"generalized"`
    ExpiresAt time.Time     `asn1:"generalized"`
    Nonce     string
    signature []byte        // 首字母小写,自动忽略
    ttl       time.Duration // 首字母小写,自动忽略
    frequency int           // 首字母小写,自动忽略
}

方式二:使用中间结构体

如果需要保留原结构体的导出字段,可以定义仅包含需编组字段的中间结构体,转换后再执行编组:

type bearer struct {
    CreatedAt time.Time     `asn1:"generalized"`
    ExpiresAt time.Time     `asn1:"generalized"`
    Nonce     string
    Signature []byte
    TTL       time.Duration
    Frequency int
}

// 定义仅包含需编组字段的中间结构体
type bearerASN1 struct {
    CreatedAt time.Time `asn1:"generalized"`
    ExpiresAt time.Time `asn1:"generalized"`
    Nonce     string
}

// 转换并执行编组
c := &bearer{
    CreatedAt: time.Now(),
    ExpiresAt: time.Now().Add(time.Minute),
    Nonce:     "123456789abcdefghijklmnop",
    Frequency: 1,
}

asn1Data := bearerASN1{
    CreatedAt: c.CreatedAt,
    ExpiresAt: c.ExpiresAt,
    Nonce:     c.Nonce,
}

b, err := asn1.Marshal(asn1Data)
if err != nil {
    // 此处添加错误处理逻辑
}
os.WriteFile("b64.txt", b, 0777)

额外修正:原代码的语法错误

原代码存在两处语法问题需要调整:

  • time.Minute是Duration常量,不是函数,需将time.Minute()改为time.Minute
  • 结构体初始化的每个字段末尾需要添加逗号,例如CreatedAt: time.Now(),

内容的提问来源于stack exchange,提问作者armaka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 03:34:52