用了Go的匿名结构体,搬砖效率更高,产量更足了

今天给大家分享一个使用匿名结构体,提升Go编程效率的小技巧,属于在日常写代码过程中积累下来的一个提升自己效率的小经验。

这个技巧之所以提效率主要体现在两方面:

  • 减少一些不会复用的类型定义
  • 节省纠结该给类型起什么名字的时间

尤其第二项,通过匿名结构体这个名字就能体现出来,它本身没有类型名,这能节省不少想名字的时间。再一个也能减少起错名字给其他人带来的误解,毕竟并不是所有人编程时都会按照英文的词法做命名的。

下面我先从普通结构体说起,带大家看看什么情形下用匿名结构体会带来编码效率的提升。

具名结构体

具名结构体就是平时用的普通结构体。

结构体大家都知道,用于把一组字段组织在一起,来在Go语言里抽象表达现实世界的事物,类似"蓝图"一样。

比如说定义一个名字为Car的结构体在程序里表示"小汽车"

go 复制代码
// 定义结构体类型'car'
type car struct {
    make    string
    model   string
    mileage int
}

用到这个结构体的地方通过其名字引用其即可,比如创建上面定义的结构体的实例

go 复制代码
// 创建car 的实例
newCar := car{
    make:    "Ford",
    model:   "taurus",
    mileage: 200000,
}

匿名结构体

匿名结构体顾名思义就是没有名字的结构体,通常只用于在代码中仅使用一次的结构类型,比如

go 复制代码
func showMyCar() {
    newCar := struct {
        make    string
        model   string
        mileage int
    }{
        make:    "Ford",
        model:   "Taurus",
        mileage: 200000,
    }
    fmt.Printlb(newCar.mode)
}

上面这个函数中声明的匿名结构体赋值给了函数中的变量,所以只能在函数中使用。

如果一个结构体初始化后只被使用一次,那么使用匿名结构体就会很方便,不用在程序的package中定义太多的结构体类型,比如在解析接口的响应到结构体后,就可以使用匿名结构体

用于解析接口响应

go 复制代码
func createCarHandler(w http.ResponseWriter, req *http.Request) {
    defer req.Body.Close()
    decoder := json.NewDecoder(req.Body)
    newCar := struct {
        Make    string `json:"make"`
        Model   string `json:"model"`
        Mileage int    `json:"mileage"`
    }{}
    err := decoder.Decode(&newCar)
    if err != nil {
        log.Println(err)
        return
    }
    ......
    return
}

类似上面这种代码一般在控制层写,可以通过匿名结构体实例解析到请求后再去创建对应的DTO或者领域对象供服务层或者领域层使用。

有人会问为什么不直接把API的响应解析到DTO对象里,这里说一下,匿名结构体的使用场景是在觉得定一个Struct 不值得、不方便的情况下才用的。 比如程序拿到接口响应后需要按业务规则加工下才能创建DTO实例这种情况,就很适合用匿名结构体先解析响应。

比用map更健壮

这里再说一点使用匿名结构体的好处。

使用匿名解析接口响应要比把响应解析到map[string]interface{}类型的变量里要好很多,json数据解析到匿名结构体的时候在解析的过程中会进行类型检查,会更安全。使用的时候直接通过s.FieldName访问字段也比map访问起来更方便和直观。

用于定义项目约定的公共字段

除了上面这种结构体初始化后只使用一次的情况,在项目中定义各个接口的返回或者是DTO时,有的公共字段使用匿名结构体声明类型也很方便。

一般在启动项目的时候我们都会约定项目提供的接口的响应值结构,比如响应里必须包含CodeMsgData三个字段,每个接口会再细分定义返回的Data的结构,这个时候用匿名结构题能节省一部分编码效率。

比如下面这个Reponse的结构体类型的定义

go 复制代码
type UserCouponResponse struct {
 Code int64  `json:"code"`
 Msg  string `json:"message"`
 Data []*struct {
  CouponId           int    `json:"couponId"`
  ProdCode           string `json:"prodCode"`
  UserId             int64  `json:"userId"`
  CouponStatus       int    `json:"couponStatus"`
  DiscountPercentage int    `json:"discount"`
 } `json:"data"`
}

就省的先去定义一个UserCoupon类型

go 复制代码
type UserCoupon struct {
    CouponId           int    `json:"couponId"`
    ProdCode           string `json:"prodCode"`
    UserId             int64  `json:"userId"`
    CouponStatus       int    `json:"couponStatus"`
    DiscountPercentage int    `json:"discount"`
} 

再在Response声明里使用定义的UserCoupon了

go 复制代码
type UserCouponResponse struct {
    Code int64  `json:"code"`
    Msg  string `json:"message"`
    Data []*UserCoupon `json:"data"`
}

当然如果UserCoupon是你的项目其他地方也会用到的类型,那么先声明,顺带在Response结构体里也使用是没问题的,只要会多次用到的类型都建议声明成正常的结构体类型。

还是那句话匿名结构体只在你觉得"这还要定义个类型?"时候使用,用好的确实能提高点代码生产效率。

总结

本次的分享就到这里了,内容比较简单,记住这个口诀:匿名结构体只在你写代码时觉得这还要定义个类型,感觉没必要的时候使用,采纳这个技巧,时间长了还是能看到一些自己效率的提高的。

相关推荐
追逐时光者2 小时前
推荐 12 款开源美观、简单易用的 WPF UI 控件库,让 WPF 应用界面焕然一新!
后端·.net
Jagger_2 小时前
敏捷开发流程-精简版
前端·后端
苏打水com3 小时前
数据库进阶实战:从性能优化到分布式架构的核心突破
数据库·后端
earthzhang20213 小时前
【1007】计算(a+b)×c的值
c语言·开发语言·数据结构·算法·青少年编程
间彧4 小时前
Spring Cloud Gateway与Kong或Nginx等API网关相比有哪些优劣势?
后端
间彧4 小时前
如何基于Spring Cloud Gateway实现灰度发布的具体配置示例?
后端
间彧4 小时前
在实际项目中如何设计一个高可用的Spring Cloud Gateway集群?
后端
间彧4 小时前
如何为Spring Cloud Gateway配置具体的负载均衡策略?
后端
间彧4 小时前
Spring Cloud Gateway详解与应用实战
后端
EnCi Zheng5 小时前
SpringBoot 配置文件完全指南-从入门到精通
java·spring boot·后端