Go言我有注释,Java说不,你没有!
发布时间:2021-11-05 07:57:43  所属栏目:语言  来源:互联网 
            导读:大家好,我是煎鱼。 作为一位 Go 程序员,你会发现身边的同事大多都拥有其他语言的编写经验。那势必就会遇到一点,要把新学到的知识和以前的知识建立连接。 图来自网络 特殊在于,Go 有些特性是其他语言有,他没有的。最经典的就是 N 位 Java 同学寻找 Go 语
                
                
                
            | 大家好,我是煎鱼。
	 
	作为一位 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 { 
	} 
	在上述例子中,通过注解去做了一系列的定义、声明、赋值等。若是对语言既有注解不熟,或是做的比较复杂的注解,就会有一定的理解成本。
	 
	在业内也常常会说,注解就是 “在源码上进行编码”,注解的存在,有着明确的优缺点。你觉得呢?
	 
	注解的作用
	在注解的的作用上,分为如下几点:
	 
	为编译器提供信息:注释可以被编译器用来检测错误或支持警告。
	 
	编译时和部署时处理:软件工具可以处理注释信息以生成代码、XML文件等。
	 
	运行时处理:有些注解可以在运行时检查,并用于其他用途。
	 
	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 项目所提供的思路来讲解。
	 
	分为三个步骤:
	 
	解析代码。
	模板处理。
	生成代码。
	解析 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 中能够获取到在示例代码中所定义的注解内容,我们就可以依据此去做很多奇奇怪怪的事情了。   (编辑:鹰潭站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! | 

