作为一位 Go 程序员,你会发现身边的同事大多都拥有其他语言的编写经验。那势必就会遇到一点,要把新学到的知识和以前的知识建立连接。

图来自网络

特殊在于,Go 有些特性是其他语言有,他没有的。最经典的就是 N 位 Java 同学寻找 Go 语言的注解在哪里,总要解释。

为此,今天煎鱼就带大家了解一下 Go 语言的注解的使用和情况。

什么是注解

了解历史

注解(Annotation)最早出现自何处,翻了一圈并没有找到。但可以明确,在注解的使用中,Java 注解最为经典,为了便于理解,因此我们基于 Java 做初步的注解理解。

在 2002 年,JSR-175 提出了 《A Metadata Facility for the Java Programming Language》,也就是为 Java 编程语言提供元数据工具。

这就是现在使用最广泛地注解(Annotation)的来源。示例如下:

// @annotation1
// @annotation2
func Hello() string {return ""
}

在格式上均以 “@” 作为注解标识来使用。

注解例子

摘抄自 @wikipedia 的一个注解例子:

//等同于 @Edible(value = true)@Edible(true)Item item = new Carrot();public @interface Edible {boolean value() default false;}@Author(first = "Oompah", last = "Loompah")Book book = new Book();public @interface Author {String first();String last();}// 该标注可以在运行时通过反射访问。@Retention(RetentionPolicy.RUNTIME) // 该标注只用于类内方法。@Target({ElementType.METHOD})public @interface Tweezable {}

在上述例子中,通过注解去做了一系列的定义、声明、赋值等。若是对语言既有注解不熟,或是做的比较复杂的注解,就会有一定的理解成本。

在业内也常常会说,注解就是 “在源码上进行编码”,注解的存在,有着明确的优缺点。你觉得呢?

注解的作用

在注解的的作用上,分为如下几点:

  1. 为编译器提供信息:注释可以被编译器用来检测错误或支持警告。

  2. 编译时和部署时处理:软件工具可以处理注释信息以生成代码、XML文件等。

  3. 运行时处理:有些注解可以在运行时检查,并用于其他用途。

Go 注解在哪里

现状

Go 语言本身并没有原生支持强大的注解,仅限于以下两种:

  • 编译时生成:go:generate

  • 编译时约束:go:build

但这先按不足以作为一个函数注解来使用,也无法形成像 Python 那样的装饰器行为。

为什么不支持

Go issues 上有人提过类似的提案:

Go Contributor @ianlancetaylor 给出了明确的答复,Go 在设计上更倾向于明确的、显式的编程风格

思考的优缺点如下:

  • 优势:不知道 Go 能从添加装饰器中得到什么好处,没能在 issues 上明确论证。

  • 缺点:是明确的,会存在意外设置的情况。

因如下原因,没有接受注解:

  • 对比现有代码方法,这种装饰器的新的方法没有提供比现有方法更多的优势,大到足矣推翻原有的设计思路。

  • 社区内的投票,支持的也很少(基于表情符号的投票),用户反馈不多。

可能有小伙伴会说了,有注解做装饰器了,代码会简洁不少。

对此 Go 团队的态度很明确:

Go 认为可读性更重要,如果只是额外多写一点代码,在权衡后,还是可以接受的。

用 Go 实现注解

虽然 Go 语言官方没有原生的完整支持,但开源社区中也有小伙伴已经放出了大招,借助各项周边工具和库来实现特定的函数注解功能。

GitHub 项目分别如下:

  • MarcGrol/golangAnnotations

  • u2takey/go-annotation

使用示例如下:

package tourdefrance//go:generate golangAnnotations -input-dir .// @RestService( path = "/api/tour" )
type TourService struct{}type EtappeResult struct{ ... }// @RestOperation( method = "PUT", path = "/{year}/etappe/{etappeUid}" )
func (ts *TourService) addEtappeResults(c context.Context, year int, etappeUid string, results EtappeResult) error {return nil
}

对 Go 注解的使用感兴趣的小伙伴可以自行查阅使用手册。

我们更多的关心,Go 原生都没支持,那么开源库都是如何实现的呢?在此我们借助 MarcGrol/golangAnnotations 项目所提供的思路来讲解。

分为三个步骤:

  1. 解析代码。

  2. 模板处理。

  3. 生成代码。

解析 AST

首先,我们需要用用 go/ast 标准库获取代码所生成的 AST Tree 中需要的内容和结构。

示例代码如下:

parsedSources := ParsedSources{PackageName: "tourdefrance",Structs:     []model.Struct{{DocLines:   []string{"// @RestService( path = "/api/tour" )"},Name:       "TourService",Operations: []model.Operation{{DocLines:   []string{"// @RestOperation( method = "PUT", path = "/{year}/etappe/{etappeUid}"},...},},},},
}

我们可以看到,在 AST Tree 中能够获取到在示例代码中所定义的注解内容,我们就可以依据此去做很多奇奇怪怪的事情了。

模板生成

紧接着,在知道了注解的输入是什么后,我们只需要根据实际情况,编写对应的模板生成器 code-generator 就可以了。

我们会基于 text/template 标准库来实现,比较经典的像是 kubernetes/code-generator 是一个可以参考的实现。

代码实现完毕后,将其编译成 go plugin,便于我们在下一步调用就可以了。

代码生成

最后,万事俱备只欠东风。差的就是告诉工具,哪些 Go 文件中包含注解,需要我们去生成的。

这时候我们可以使用 //go:generate 在 Go 文件声明。就像前面的项目中所说的:

//go:generate golangAnnotations -input-dir .

声明该 Go 文件需要生成,并调用前面编写好的 golangAnnotations 二进制文件,就可以实现基本的 Go 注解生成了。

总结

今天在这篇文章中,我们介绍了注解(Annotation)的历史背景。同时我们针对 Go 语言目前原生的注解支持情况进行了说明。

也面向为什么 Go 没有像 Java 那样支持强大的注解进行了基于 Go 官方团队的原因解释。如果希望在 Go 实现注解的,也提供了相应的开源技术方案。

你觉得 Go 语言是否需要像和 Java 一样的注解支持呢?

欢迎在评论区交流和讨论!

本文转载自公众号脑子进煎鱼了,如需转载请点击下方联系作者。

关注煎鱼,吸取他的知识 

假如给Go语言加上注解,程序会变怎样?相关推荐

  1. Java语言使用注解处理器生成代码——第三部分:生成源代码

    原文作者:deors 原文地址:https://deors.wordpress.com/2011/10/31/annotation-generators/ 译文作者:Jianan - qinxiand ...

  2. c语言的程序灵魂是什么,C语言 第二章 程序的灵魂--算法

    <C语言 第二章 程序的灵魂--算法>由会员分享,可在线阅读,更多相关<C语言 第二章 程序的灵魂--算法(39页珍藏版)>请在人人文库网上搜索. 1.第二章 程序的灵魂-算法 ...

  3. 常用c语言小程序,c语言经典小程序汇总大全

    网上有很多的人说编程有多么多么无聊,其实:不要管别人怎么说,别人说什么,做你自己喜欢做的事就好.坚持下来,你会发现编程的乐趣的.当然,如果你觉得学习编程语言很痛苦,坚持了一段时间后无果,南无果断放弃未 ...

  4. c语言笔记——黑马程序员上课笔记

    C语言概述 1.1 什么是C语言 一提到语言这个词语,自然会想到的是像英语.汉语等这样的自然语言,因为它是人和人交换信息不可缺少的工具. 而今天计算机遍布了我们生活的每一个角落,除了人和人的相互交流之 ...

  5. 都2023年了,你如果还不知道这18个C语言入门经典程序就亏了

    作为一个C语言初学者,如何学代码很重要!俗话说得好,当我刷完每一年的题,就没有我不会的题了,而C语言不需要这么麻烦,他需要记得东西其实不多,基本是哪个就是几个常见的语句加上一些关键字而已.你所看那些大 ...

  6. 易语言写的程序如何加密防止别人破解

    1.花指令的插入,这当然是有必要的,有人说加了花指令没有什么用,现在的反编译软件基本上都有去除花指令的功能,但是难道它能去我就不加了?给破解者增加一点麻烦事也是好的嘛! 2.加壳,现在的很多壳都有自动 ...

  7. c语言通讯录二分查找,C语言程序设计 通讯录程序.doc

    <C语言程序设计 通讯录程序.doc>由会员分享,可在线阅读,更多相关<C语言程序设计 通讯录程序.doc(28页珍藏版)>请在人人文库网上搜索. 1.目录:课 程 设 计 任 ...

  8. python输入一个正整数n求下列算式的值_C语言编写程序:输入一个正整数x和一个正整数n,求下列算式的值。,C语言 编写一个程序,输入一个正整数,求出它是几位数。...

    导航:网站首页 > C语言编写程序:输入一个正整数x和一个正整数n,求下列算式的值.,C语言 编写一个程序,输入一个正整数,求出它是几位数. C语言编写程序:输入一个正整数x和一个正整数n,求下 ...

  9. 开发语音录入_语言翻译小程序app开发 解决了人们的语言障碍问题

    随着经济的发展,人们经济水平的提高,促进了国际交流越来越频繁,人们出国的次数也是越来越多.但是语言交流也是日常的障碍,给诸多的人带来不便.出国旅游要是语言不通还会影响旅游质量.语言翻译小程序的开发,便 ...

最新文章

  1. 【ZooKeeper】配置文件详解
  2. ERP实施成功与否,企业文化是致命因素?
  3. 百度代码规范 -- PHP
  4. 免费的SEO工具软件大全
  5. Android UI之ImageView
  6. 辗转相除最小公倍数的递归求法
  7. javafx 自定义控件_JavaFX自定义控件– Nest Thermostat第1部分
  8. CS231n Convolutional Neural Networks for Visual Recognition------Numpy Tutorial
  9. Apache beam其他学习记录
  10. freecplus框架-日期、时间和计时器
  11. IIS搭配Server-u构建企业空间服务(二)
  12. Struts 1.x 的工作原理
  13. 狮子鱼社区团购独立版安装方法
  14. 非平衡电桥电阻计算_用非平衡电桥测量电阻
  15. RGB888和RGB565颜色对照表
  16. 2003迁移2008R2难点分析
  17. 迅雷iOS端安装 - iPhone安装手机迅雷
  18. Wex5打包报错的解决办法
  19. 辣椒疫霉RXLR效应子抑制植物免疫
  20. 成长中必知的20个故事[转]

热门文章

  1. 史上最快、最强大的Gradle 5.0发布,新特性全解
  2. 【Android】日常问题记录
  3. ArcGIS Server 10.1发布结果地图服务——与10.0的区别及过程
  4. Java数据库驱动链接大全
  5. react-native ListView 封装 实现 下拉刷新/上拉加载更多
  6. 基于React的全屏滑动插件react-fullslip
  7. C#将DLL嵌入到exe当中
  8. 【原创】MySQL里求给定的时间是所在月份的第几个礼拜
  9. Android ContentProvider的介绍(很详细)
  10. 配置gitlab环境实现代码管理及Web Hook测试和ldap认证