前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >go结构体中的匿名变量在json.marshal中隐藏的坑

go结构体中的匿名变量在json.marshal中隐藏的坑

原创
作者头像
谢盼
发布2020-03-26 11:52:41
3.7K0
发布2020-03-26 11:52:41
举报
文章被收录于专栏:视频AI视频AI

故障背景

在昨天的工作中,遇到一个诡异的小问题,调试了一段时间,在网上也没有找到相关材料(可能谷歌能力有限,搜索不到,要用百度)。先来看一段简单的简化后的代码,简单、清晰、明了、接地气,与我的工作场景一致。

代码语言:javascript
复制
/*
 * Copyright (c) 2020.
 * panxie@tencent.com
 */

package main

import (
   "encoding/json"
   "fmt"
)

type L5 struct {
   Modid int64 `json:"modid"`
   Cmdid int64 `json:"cmdid"`
}

type CommonAttr struct {
   Name string `json:"name"`
   Desc string `json:"desc"`
}

type OperationQueryCKV struct {
   L5       
   Expression string `json:"expression"`
   TimeoutMs  int64  `json:"timeout_ms"`
}

type Operation struct {
   CommonAttr
   *OperationQueryCKV
}

func main() {
   op := &Operation{
      CommonAttr{
         Name: "op_name",
         Desc: "op_desc",
      },
      &OperationQueryCKV{
         L5: L5{
            Modid: 12345,
            Cmdid: 54321,
         },
         Expression: "expression",
         TimeoutMs:  80,
      },
   }
   b, _ := json.MarshalIndent(op,"","\t")
   fmt.Printf("%s\n", string(b))
}

关注一下L5结构,这是一种公司内部服务负载均衡和服务发现的公共件,简单的说,一个L5可以换到一个IP和端口列表,然后拿去访问服务。对于CKV查询功能来说,需要一个L5表明CKV在哪。

漫天飞舞的匿名字段,是不是像golang大神特有的标签。运行一下,没问题,符合预期,完美。

代码语言:javascript
复制
[root@VM_15_146_centos ~]# go run main.go
{
        "name": "op_name",
        "desc": "op_desc",
        "modid": 12345,
        "cmdid": 54321,
        "expression": "expression",
        "timeout_ms": 80
}

故障现象

有一天,这样跑了一年的代码突然就不对了,测试发现,OperationQueryCKV结构序列化之后modid和cmdid都消失了,很邪乎。告诉我这个问题后,我也是一脸懵,我最近没有改动相关代码呀。都跑了一年了你跟我说这东西不行了?

故障原因

查看代码提交记录,一处改动进入视野,最近新增了一个查询数据库的功能,与OperationQueryCKV类似的,新增定义了一个OperationQuerySQL,只是新定义了结构,还没有实现和严格测试。

代码语言:javascript
复制
type OperationQuerySQL struct {
   L5   
   User string `json:"user"`
   Pwd  string `json:"pwd"`
}

type Operation struct {
   CommonAttr
   *OperationQueryCKV
   *OperationQuerySQL 
}

查询数据库也需要一个L5,一贯风格,新增一个L5的匿名变量,完活。估计就是两个匿名L5,把值搞没了。试着跑一下样例代码。

代码语言:javascript
复制
func main() {
   op := &Operation{
      CommonAttr{
         Name: "op_name",
         Desc: "op_desc",
      },
      &OperationQueryCKV{
         L5: L5{
            Modid: 12345,
            Cmdid: 54321,
         },
         Expression: "expression",
         TimeoutMs:  80,
      },
      nil,
   }
   b, _ := json.MarshalIndent(op, "", "\t")
   fmt.Printf("%s\n", string(b))
}

结果,我的L5果然没有了。根本原因应该是匿名变量导致的json字段key重复。

代码语言:javascript
复制
{
        "name": "op_name",
        "desc": "op_desc",
        "expression": "expression",
        "timeout_ms": 80
}

解决方法

这样的坑,在分工合作时会不经意引入,有时比较隐晦。

暂时也不知道好的办法,建议是不用或者少用匿名字段,如果需要使用匿名字段,每项都定义不同的`json:"_key_“`。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 故障背景
  • 故障现象
  • 故障原因
  • 解决方法
相关产品与服务
负载均衡
负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档