为什么不用刻意去学一门编程语言

一.引言

多年来,我没有主动刻意去选择一门编程语言去学习, 无论做什么形式的工作, 首先考虑解决问题的实际效率问题, 逼自己提高工作效率实际上是另一种摆脱舒适区的比较好的方法。一个任务摆在眼前, 为了提高工作效率我会查阅很多资料, 包括: 使用什么编程语言, 各自有什么优缺点; 该使用什么样的架构, 我选择的编程语言有没有成熟的框架, 性能如何等等都会去调研。

在这个过程中首先我可以临时接受一门新的编程语言去学习, 但必须能让我很快上手, 最长学习时间不超过一周即可正常投入到工作中;其次会考虑编程语言的复杂性问题, 这个复杂性包括支持的库是否丰富、是否能够方便跨平台、是否能够方便部署等;最后是该编程语言是否有比较系统的文档和成熟的社区, 方便查阅和解决问题。

二.汇编/C/C++

首先接触这三门语言跟我第一份正式工作内容有关, 我的第一份工作是做计算机病毒分析, 在逆向分析病毒行为的过程中, 需要在反汇编环境下观察堆、栈和寄存器内容的一举一动, 所以汇编语言属于基本功, 几乎天天打交道。另外在系统编程、嵌入式开发、游戏开发、驱动程序开发、软件加密解密等领域也经常能见到汇编语言的身影。

逆向分析中的汇编语言

随着工作性质的转变, 需要编写病毒的专杀工具来供用户使用, 普通用户当然需要一个界面来操作, 当时能够快速上手画界面并快速进行事件响应的非MFC莫属, MFC是微软基于C++开发的应用程序框架,充分利用了C++的面向对象特性, 并提供了诸如文档/视图架构、事件处理等基于C++封装的功能, MFC通过类封装了Win32 API的许多功能,简化了C++语言调用Windows API的复杂性, 在使用MFC开发病毒专杀工具的过程中, 对C++的特性也逐步熟练。

专杀工具样例

随着病毒的不断升级, 驱动级病毒也越来越普遍, 与病毒的对抗逐步由Ring3环转到Ring0环。编写驱动级病毒对抗程序经常会涉及文件过滤驱动、内核模式钩子等技术, 在Windows驱动开发中, 驱动程序代码主要使用C语言编写,微软的驱动开发工具WDK也是针对C语言的,而内核级编程需要直接调用Windows内核的本机API, 这些API接口也是用C语言编写的, 例如:利用内核钩子和过滤驱动对病毒进行拦截,涉及到编写处理病毒的C语言函数,在反汇编病毒二进制代码后得到的汇编语言代码,仍可以看到病毒实现的关键C语言函数,在使用Windbg进行内核调试时,可以对驱动程序的C语言源代码进行单步追踪,利用C语言可以调用WindowsAPI实现一些检测病毒的关键功能,因此C语言可以说是驱动级对抗程序开发的基石, 熟练掌握C语言在这个阶段必不可少。

文件过滤驱动样例

三.Java/Lua语言

随着个人手机的不断普及, 大概从2011年开始, Android手机病毒逐步增多, 在逆向Android病毒的过程中, 我学会了jar包的反编译, 同时也学会了重打包, 自然也开始接触到Java语言,但个人对Java并没多大兴趣, 因为当时从心里觉得, 学Java的人实在太多, 高手也很多, 对于我来说没有什么竞争优势, 形成不了技能壁垒, 因此果断的放弃了Java语言的学习。

不过Java语言在大型商务网站, 与政府单位网站进行功能对接的项目中用的还是非常广泛的,毕竟Java生态有非常成熟的框架、整体解决方案和服务支持。

后来又接触到一个跟路由器相关的技术研究任务, 路由器使用的系统为OpenWRT, 并且提供了一个管理界面, 该界面的后端采用Lua语言编写,Lua语言是一门轻量级语言,编译器和解释器极小,可嵌入到其他应用程序。由于Lua语言具备语法灵活自由,支持面向过程和函数式编程,自动内存管理,可扩展性强,执行效率高等优点, 因此在游戏开发、嵌入式系统、Web应用、机器人、物联网和人工智能领域使用较为广泛。OpenWRT系统是一款著名的嵌入式Linux发行版,主要用于无线路由器, 而OpenWRT也支持Lua脚本,其后端主要通过Lua脚本实现, 因此要想完全自主控制路由器的功能, 必须在Lua原脚本代码中进行改造, 熟练掌握Lua语言必不可少。

Openwrt界面

四.Perl语言

我的第一个爬虫是使用Perl语言完成的, Perl语言的特点是跨平台,处理字符串功能强大,提供了丰富的正则表达式支持, 由于Perl语言采用了类C的语法, 有C语言基础的特别容易上手, 在一些特定领域具有独特的优势,例如:

  • 文本处理 - 过滤日志、解析配置文件等

  • 系统管理 - 系统监控、备份等运维自动化

  • 网络编程 - 网络协议、SOCKET编程

  • CGI编程 - 用作服务端CGI脚本语言

  • 数据处理 - 文件格式转换、数据分析等

  • 云计算 - 用于部分云平台的自动化脚本

Perl的字符串处理能力与成熟的模块生态系统,使其在文本处理和系统管理方面有着比较广泛的使用, 但缺点也很明显: 语法不是很严谨,可读性较差;运行速度中等,不适合高性能场景,代码可维护性较差,开发活跃度也不及以往。

Perl代码

五.Python

首次接触Python语言是在2016年, 当时研究的主要项目是跟网络反诈骗相关, Python语言主要有两大优势:

1.上手和开发效率特别高, 语法简洁、库丰富, 在用Python处理Excel数据过程中感觉非常舒适, 所以我更多的是使用Python进行运营方面的工作, 包括: 特定文件内容数据的批量处理, 管理维护类的杂项功能。

2.Python在数据分析、科学计算和人工智能方面有得天独厚的优势,例如用于数据分析的NumPy、Pandas、SciPy、Matplotlib。用于科学计算的SymPy、Scikit-learn、大名鼎鼎的TensorFlow等。用于人工智能的NLTK、OpenCV和Keras等。

尽管Python优势这么明显, 但在学习过程中仍然遇到一些问题, 这其中包括: Python版本及第三方库版本差异带来的问题、pip软件使用问题、代码部署问题, 在解决这些问题上也没少花时间。

Python代码

六.Go语言

我正式接触Go语言是在2017年, 当时有个小项目抽不出人手, 只有由我一个人开发, 开发周期只有4个月时间, 在评估完需求之后, 我开始针对性的编写技术方案, 在查找资料的过程中意外发现Go语言的一些特性跟我的项目非常契合。契合点主要包括以下几个方面:

(1).上手快且开发效率高

因为之前有C/C++、Python的开发经验 , 所以我大致了解了一下Go的基本语法就能上手写一些功能了, 而且Go本身就是C语言开发的, 里面有些语法可以看到C语言的痕迹,例如:结构体、指针等。但与C语言不同的是, Go语言去掉了C语言中的大括号、分号等元素, 使其语法简单明了, 更易读易写。另外,Go语言引入了自动垃圾回收机制, 不用像C/C++那样需要自己管理内存, 虽然失去了精确控制内存的灵活性, 但程序稳定性得到大幅度提升, 提高了整体开发效率。

(2).内存占用低且高并发

Go语言中引入了协程(goroutine)概念, 协程与其它高级语言的线程不同, 协程的调度器被放在用户层空间,而不是内核空间, 从而在做协程之间切换时不需要经过内核,切换开销才几十纳秒, 调度开销非常低廉且高效, 而线程切换则是以微秒计算, 调度开销远大于协程。

再来看看内存开销, 协程能够达到轻量级, 主要由以下因素构成:

(1).协程没有像线程那样需要线程控制块来维护线程信息,且在上下文切换时,只需保存少量寄存器等信息,而不需要保存整个栈。

(2).Go语言同一个程序内的所有协程共享堆空间,不需要重新分配。

(3).Go语言的运行时复用机制可以在多协程运行过程中, 复用未激活的协程,尽量减少内存开销。

(4).协程由Go语言的运行时(runtime)管理,减少了外部程度的内存开销。

(5).Go语言的通道(channel)可以使协程之间进行无锁通信,节省了锁空间。

由以上机制带来的好处就是:Go语言的协程默认栈空间仅仅只有2KB-4KB左右,而其它高级语言的线程默认占用内存空间在512KB-1MB。

Go语言如果开启100万个协程,也仅仅占用200MB-400MB内存空间, 而其它同样使用100万线程的高级语言内存开销则是惊人的100GB内存。而且这只是线程栈开销, 如果算上线程对象开销,通常为几十KB,100万则会额外占用5GB内存。当然,在实际工作中,还没考虑线程的阻塞开销,大量线程有很大几率会造成竞争和阻塞,这样也会消耗一定内存。而像Java语言,还要算上JVM本身的内存开销。

(3).跨平台方便

Go语言具备十分简洁的编译命令,通过设置GOOS和GOARCH等环境变量即可控制目标平台。Go语言采用自主研发的对象文件格式和编译器, 使得Go语言可以不依赖目标操作系统可以将同一套代码编译到不同的操作系统上运行。

在Go的标准库和工具链中内置了支持多种主流操作系统和处理器。当我们在安装了Go开发包的机器上输入命令: go tool dist list 即可看到Go语言支持的所有操作系统和CPU架构,如图:

我可以轻易编译出上面列表平台上运行的可执行程序,例如:

(1).编译在Windows x64上执行的程序:

CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o main.exe

(2).编译在Linux x64上执行的程序:

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o main

(3).编译在树莓派(或者单片机)上执行的程序:

32位:CGO_ENABLED=0 GOOS=linux GOARCH=arm go build -o main

64位:CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o main

(4).编译支持在Apple M1/M2芯片上执行的程序:

CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -o main

(5).编译支持在macos上执行的程序:

CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o main

(4).编译速度快且部署简单

Go语言作为全静态编译语言, 代码编译速度都是秒级, 连Rust都相形见拙。Go语言编译完成后,只有一个二进制可执行程序, 我曾经在一个项目中看到用全Python写的代码, 但在线上环境运行过程中, 却使用Docker启动了十几个Python容器, 也看到有些项目在生产环境没有网络环境的情况下, 要上传几百兆的Docker离线容器或一堆依赖包, 但对于Go语言来说, 哪怕机器是个裸机, 我只用上传编译好的一个二进制程序, 假设这个二进制程序名为: main, 我只用以下操作即可部署完成:

chmod +x main (给予可执行权限)

./main &. (后台运行)

全程0依赖包, 0 Docker容器。

七.Rust语言

我正式接触Rust语言是在2021年, 虽然没有像Go一样在项目中一样使用的非常频繁, 但一直在持续学习和关注其发展。在当年的StackOverflow调查中,Rust成为最受欢迎的语言, Rust作为一门新兴语言, 却有着比较完整的生态系统, rust拥有包管理器Cargo、构建工具rustc等比较成熟的工具链, crates.io上拥有超过5万个包, 有比较成熟的Web框架例如:Actix、Rocket等。最主要的是rust语言受到很多巨头公司的青睐和支持,例如:Microsoft、Amazon和Google。

Rust相比其他编程语言,有着自身一些独特的优势,很值得我们学习,例如:

  • 内存安全问题 - Rust的所有权系统可以保证内存安全,避免野指针错误、缓冲区溢出等问题, 这也是Rust的最大卖点。

  • 性能问题 - Rust的运行时极小,抽象成本低,可编译为原生代码,性能可与C/C++媲美。

  • 范型编程 - Rust有更高级的范性系统, 可以实现轻量级的抽象, 提高代码复用性。

  • 更严格的一致性 - Rust严格的类型系统与显示错误处理, 可以建立更一致、可靠的大型程序。

  • 并发安全 - Rust的Send/Sync系统提供并发安全保证,使并发编程更安全简单。

  • 函数式编程特征 - Rust支持高阶函数、闭包、惰性计算等函数式编程能力。

  • 出众的文档系统 - Rust文档齐全,各语言特性都有详尽的官方文档介绍。

然而, Rust的一些新特性却成为开发人员的入门难点,难点主要有以下几个方面:

  • 所有权(Ownership)系统 - 需要改变编程思维方式,不熟悉会造成代码无法编译。

  • 借用(Borrowing)机制 - 理解引用的作用域和生命周期, 避免dangling pointer。

  • 生命周期(Lifetime) - 了解引用、变量、数据的生命周期关系。

  • trait对象动态分发 - Rust的trait模型比传统OOP更复杂。

  • 并发模式 - Rust的并发安全保障需要学习新的并发模式。

  • 错误处理 - 了解Result等错误处理方式。

目前越来越多的商业程序和开源项目正逐步使用Rust语言进行重构或编写,比较有代表性的项目如下:

  • Mozilla - Firefox浏览器中的一些组件,如新引擎Servo使用Rust开发。

  • Microsoft - Windows、Azure云平台中的一些模块;编译器成分Rust Analyzer。

  • Amazon - AWS云平台的Firecracker虚拟机管理程序。

  • Google - Android操作系统内核组件; Fuchsia OS中广泛使用Rust。

  • Dropbox - 存储服务客户端内部的一些关键网络库采用Rust。

  • Facebook - 分布式数据库Tornado使用Rust;扩展了Rust在WebAssembly的应用。

  • Red Hat - Linux操作系统中一些性能敏感的组件用Rust改写。

  • Nvidia - GPU驱动程序中的服务和工具,以提高安全性。

  • Cloudflare - 一些网络功能组件,如反向代理、分布式KV存储。

  • Parity - 密码货币钱包Parity、Polkadot区块链。

Rust带来的内存安全和性能优势,正在被云服务、操作系统、区块链等要求高可靠性的领域所认可和采用。

八.总结

以自己的发展方向为目标, 工作内容尽量不要偏离自己的发展目标, 否则自己将来的知识很难构成体系, 在这个基础上, 逐步去接触各类编程语言, 用来解决工作中的实际问题, 只有这样,才可能更容易将知识点逐步以点盖面, 建立起自己的知识网络。

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二进制空间安全

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值