热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

go语言宏,golang宏

golang怎么在release版本避免编译一些代码很遗憾,Go中没有这样的设计,当然,目前大多数相对高级的语言都取消了宏定义的方法,虽然这样降低了程序员对程序的掌控能力,但是这样

golang怎么在release版本避免编译一些代码

很遗憾,Go中没有这样的设计,当然,目前大多数相对高级的语言都取消了宏定义的方法,虽然这样降低了程序员对程序的掌控能力,但是这样更容易保证程序运行的一致性。俗话说,有舍也有得吧。

对于想要实现Release版本与Develop版本体现不一样的运行效果,可以通过定义特殊的标记常量或者变量来实现,这一点在Java等很多语言上都是一样的。

现代编程语言那些让人激动的特性

有没有觉得,发展到现在,软件开发行业是越来越成熟了,无论是过程管理、架构方法、设计方法,还是语言、平台、框架、工具等,都发展到了一个前所未有的高度,相关思想和理念也日臻完善,我们真正进入了一个最好的时代。

单就编程语言来说,近些年包括Scala(2003)、Groovy(2003)、Go(2009)、Kotlin(2011)、Swift(2014)等新兴编程语言如雨后春笋版涌现出来,也给我们带来了很多让人眼前一亮的编程特性,甚至Java这等老牌编程语言也是不断推陈出新,编程再也不像过去那般枯燥。

本篇就带大家一起感受一下现代编程语言那些激动人心的特性。

这个特性其实有点早了,但是也是很早就让人感动的语言特性了,熟悉Javascript的同学应该对它很了解。Javascript语言具有动态性,我们可以随时为类的某个实例添加方法,也可以利用动态原型,为类的所有实例添加方法,有没有感觉扩展类的实现变得非常方便了呢?

扩展和原型很像,允许我们在不修改或继承类的情况下,将新的函数方法添加到原类中。这个特性较早见于C#这门语言,目前在Kotlin、Swift中均可以看到。这里顺便说一下C#,当时C#出来的时候,不得不说很多特性是非常棒的,包括扩展方法、泛型、分部类等等,比Java好不要太多。像Kotlin,不仅可以扩展类的方法,还可以扩展类的属性。

前两个都是关于扩展代码的,这里再来一个。我们知道Java 1.8以来,接口interface里的方法可以有自己的默认实现了,大大方便了实现类,减少了重复代码。相对于Java的这个实现是显示的,Go语言的接口实现可以是隐式的,添加隐式实现后,所有继承的结构(Go没有类,都是结构struct)都可以调用这个方法,和前面的两个特性有异曲同工之妙,下面我们对比看一下。

C语言就有宏的概念,通过 #define 定义,然后在代码中进行替换。宏作为Rust语言的高级特性,可以操作语法单元,是一种通过编写代码来生成代码的方式,被称作“元编程”(meta programming)。相对于函数,宏可以接受任意多个参数,可以减少重复代码,定义DSL。宏语法比较复杂,难以编写和调试,以至于在Rust文档中说,宏将是其最后的特性。

当你回想写代码枯燥的时候,应该会想到为字段编写getter、setter吧?较早的时候,C#就意识到了这个问题,贴心地推出了自动属性这个语法糖。而Java开发者则是通过Eclipse、IDEA这样的开发工具来自动生成getter、setter代码。当然,现在也可以依赖Lombook包,使用lombok的注解@Getter @Setter来编译时生成相关代码。

据说空指针异常是软件业最贵的异常,价值10亿美元。你有没有为处理调用链中的null值而烦恼过?又或者被伤害过?Kotlin会在编译期提示对可能为null变量的不安全使用,也提供了Elvis 操作符 ?: 来方便地处理null值。而有了可选链,就舒服多了。可选链语法应该较早出现在Javascript语言中,新兴语言Swift也提供了这一省心的特性。Swift英明地决定变量是不允许直接存储NIL值,当然也提供了optionals的装箱功能允许将NIL或其它值包装起来,方便有时使用。

输入乃万恶之源,函数首要的事情就是检查不规范和不安全的输入,这也是卫语句的来历。Swift语言为此提供了专门的卫语句语法,有了它的贴身防护,整个代码都干爽多了,剧烈运动都不怕,不信往下瞧:

如果要评选最酷的语言特性,那么Lambda表达式必须获得提名。Lambda表达式很早就出现在Lisp语言中,python也有,在后来的C#语言大放异彩,又一次狠狠地羞辱了不长进的Java,而Java也终于在1.8版本后加入了这一特性,甚至C++ 11也光荣地上车了。

我们知道编程语言有静态和动态之分,静态语言如Java 、 C# 、 C 和 C++,动态语言如Perl,Python,Javascript,Ruby 和 PHP等,多数为脚本语言。而融合了静态和动态特性的语音,就被称为渐进式语言,如TypeScript、Common LISP、Dylan、Cecil、Visual Basic.NET、Bigloo Scheme、Strongtalk等。静态类型检查可以尽早地发现 BUG,动态类型检查可以方便地处理依赖于运行时信息的值的类型。 渐进式语言允许类型注释来控制程序的一部分使用静态类型检查,而另一部分为动态检查,更具灵活性。 Python从3.5开始引入了对静态类型检查的支持。

在面向对象的编程语言中,状态是计算的基础。由于可变状态的存在,在编写高并发,多线程代码时,无法知道并行进行的诸多状态读写中是否有顺序上的错误,而且这种错误又是难以察觉的,而不变性则规避了这个问题。 不变性是函数式编程的基础,不变性意味着函数没有副作用,无论多少次执行,相同的输入就意味着相同的输出,所有线程都可以无所顾忌的执行同一个函数的代码,代码更像数学函数,更易理解和测试。

String就是构建在Java语言内核中的不可变类的一个典型例子。Java 的 CopyOnWrite系列容器类也是利用了不变性增强了并发安全性。Java可以通过final修饰符实现类和变量的不可变。而Scala、Swift、Groovy等语言也有各自的语法实现不可变的变量和类。

多重分派是一些编程语言的特性,其中的函数或者方法,可以在运行时间(动态的)使用一个或多个实际参数的组合特征,路由动态分派至实现函数或方法。多重分派主要区别于我们常见的重载方法,重载方法是在编译期就绑定了,而多重分派是在运行期分派的。Lisp、Julia、C#、Groovy等语言内建多分派特性,Javascript、Python和C等语言通过扩展支持多分派。 多重分派可以避免我们写很多分支条件,而是更直观地用对象类型表达,使代码变得可读性更好并且较少发生错误。

前面几个特性是不是略显沉闷,那么来看一下这个激动一下。解构这一语法特性用于从数组索引或对象属性创建变量,简直帅到飞起。

爱写单元测试的同学有福了,这个绝壁是重磅炸弹,在生产代码里夹着测试代码,你有想过这么写测试吗?谁想的?简直脑洞打开啊!该特性在Pyret语言中,Pyret旨在作为编程教育的杰出选择,同时 探索 脚本和函数式编程的融合。

如果内联测试没有让你震惊,D语言内联编译期的这个特性绝对会让你惊掉下巴,基于该特性,开发人员可以直接在D语言中嵌入汇编代码,彻底放飞自我了,俺滴亲娘啊!受不了!受不了!顺便说一下,D语言比较小众,是C++的一个改进型,它包括了按合约设计、垃圾回收、关联数组、数组切片和惰性求值等特性。

好吧,我们看点其它的来压压惊吧。尽管Kotlin语言也说自己实现了模式匹配,但是实际上只是一点点帅,真正帅的是 Elixir语言的模式匹配,Elixir作为一种在Erlang OTP上运行的动态类型语言,将模式匹配提升到了一个全新的水平。

在编程语法上,Python真是个神一样的存在,for循环都能写出花来。

Java 8 中提供了Stream API特性, Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式,来提供一种对 Java 集合运算和表达的高阶抽象。事实上这个特性C#早就有了(Java又躺枪一次)。不得不说,利用这个特性写出来的代码,看上去还真的是很流利的。

golang项目中使用条件编译

golang中没有类似C语言中条件编译的写法,比如在C代码中可以使用如下语法做一些条件编译,结合宏定义来使用可以实现诸如按需编译release和debug版本代码的需求

build tags 是通过代码注释的形式实现的,要写在文件的最顶端;

go build指令在编译项目的时候会检查每一个文件的build tags,用来决定是编译还是跳过该文件

build tags遵循以下规则

示例:

约束此文件只能在支持kqueue的BSD系统上编译

一个文件可能包含多行条件编译注释,比如:

约束该文件在linux/386 或 darwin/386平台编译

需要注意的点

正确的写法如下:

编译方法:

具有_$GOOS.go后缀的go文件在编译的时候会根据当前平台来判断是否将该文件导入并编译;同样适用于处理器架构判断 _$GOARCH.go。

两者可以结合起来使用,形式为: _$GOOS_$GOARCH.go

示例:

文件名必须提供,如果只由后缀的文件名会被编译器忽略,比如:

这两个文件会被编译器忽略,因为以下划线开头的文件都会被忽略

对比Go 语言,Rust 有什么优势和劣势

对于Rust的优势我的体会如下:

* Error Handling机制好太多,用Result封装函数运行结果灵活性大大提高,代码也大大简洁

* 函数式编程支持较好,有Lambda这种东西,使得它写起来甚至有Ruby的感觉

* 效率高,没有了GC和Runtime,速度是没得说的

* 支持范型

* 有宏和编译器插件这些黑客技,语言扩展性较好

* 社区活跃度更高,更强调社区的作用,有[RFC](GitHub - rust-lang/rfcs: RFCs for changes to Rust)。[中文社区](Rust China)也有了

Rust的劣势是:

* 语言特性复杂,对新手就不会那么友好

* 稳定性不够,语言的进化较激进

* 第三方库的成熟度还落后于Go,商业化的应用也还不够

go语言为什么没有min/max函数

go语言math包里面定义了min/max函数,但是是float64类型的,而并没有整数类型的min/max。

因为go没有重载,这是个大坑。所以math库里min/max函数都只能定义一个,所以官方选择了比较难实现的float64类型。而简单的整形就需要让程序员自己实现了

go语言的参数怎么实现const修饰的效果'

const修饰的数据类型是指常类型,常类型的变量或对象的值是不能被更新的。const关键字的作用主要有以下几点:(1)可以定义const常量,具有不可变性。例如:cOnstintMax=100;intArray[Max];(2)便于进行类型检查,使编译器对处理内容有了解,消除了一些隐患。例如:voidf(constinti){}编译器就会知道i是一个常量,不允许修改;(3)可以避免意义模糊的数字出现,同样可以很方便地进行参数的调整和修改。(4)可以保护被修饰的东西,防止意外的修改,增强程序的健壮性。还是上面的例子,如果在函数体内修改了i,编译器就会报错;例如:voidf(constinti){i=10;//error!}(5)为函数重载提供了一个参考。classA{voidf(inti){}//一个函数voidf(inti)const{}//上一个函数的重载};(6)可以节省空间,避免不必要的内存分配。例如:#definePI3.14159//常量宏cOnstdoulbePi=3.14159;//此时并未将Pi放入ROM中doublei=Pi;//此时为Pi分配内存,以后不再分配!doubleI=PI;//编译期间进行宏替换,分配内存doublej=Pi;//没有内存分配doubleJ=PI;//再进行宏替换,又一次分配内存!const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。(7)提高了效率。编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。


推荐阅读
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 本文比较了eBPF和WebAssembly作为云原生VM的特点和应用领域。eBPF作为运行在Linux内核中的轻量级代码执行沙箱,适用于网络或安全相关的任务;而WebAssembly作为图灵完备的语言,在商业应用中具有优势。同时,介绍了WebAssembly在Linux内核中运行的尝试以及基于LLVM的云原生WebAssembly编译器WasmEdge Runtime的案例,展示了WebAssembly作为原生应用程序的潜力。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 这篇文章主要讲解了“如何应对Android面试”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何应对 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • Java实战之电影在线观看系统的实现
    本文介绍了Java实战之电影在线观看系统的实现过程。首先对项目进行了简述,然后展示了系统的效果图。接着介绍了系统的核心代码,包括后台用户管理控制器、电影管理控制器和前台电影控制器。最后对项目的环境配置和使用的技术进行了说明,包括JSP、Spring、SpringMVC、MyBatis、html、css、JavaScript、JQuery、Ajax、layui和maven等。 ... [详细]
  • 原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
  • java.lang.Class.getDeclaredMethod()方法java.lang.Class.getDeclaredMethod()方法用法实例教程-方法返回一个Met ... [详细]
author-avatar
小豇豆和花椰菜
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有