通用基础培训

87 阅读6分钟

编程语言

我们知道的语言有很多,例如 JavaScript,Java,C,C++,C#, Go,PHP, Python等等各种语言。那么为什么会有这么多语言。答:因为每种语言的侧重点不同,或者是立场不同。

例如:

  • JavaScript 多用于写网页端;
  • C和C++多用于硬件开发或者需要速度比较快的地方;
  • Java 和 C# 是两个永远拿来对比的语言
  • PHP是世界上最好的语言

强类型语言

强类型语言: 是一种强制类型定义的语言,一旦某一个变量被定义类型,如果不经过强制转换,则它永远就是该数据类型了,强类型语言包括Java、C# 、Python、C++等语言。

弱类型定义语言:数据类型可以被忽略的语言。它与强类型定义语言相反, 一个变量可以赋不同数据类型的值。

例如:

java 中 String test = "100";

JavaScript 中 var test = "100";

编译型和解释型

编译型:一次把所有的代码转换成机器语言,然后写成可执行文件。

解释型:解释,执行,再解释,再执行,你到哪里,给你整。

编译型的程序执行效率高,依赖编译器,跨平台性差,例如C语言。解释型的每个语句都是执行的时候才翻译。效率比较低,例如JS,Python。还有一些取中间的,比如java,c#,先编译成中间态,又不是机器最终机器执行的代码,又不是等到运行的时候才跑来解释再运行。

怎么选

那么多语言,我们怎么分,怎么选呢?可能有些同学看了以后会说:

听君一席话,胜似一席话。

我自己的理解是:没有完美的语言,每种语言都有自己的优点,它没有被淘汰,它还存在,说明它有存在的必要。

例如经常听到的问题是,你们的后台怎么用xxx写呢?你们为什么不用xxx呢?经常有这种乱七八糟的,相信有的同学也遇到过:

  1. 历史问题: 这个系统比我在这个公司的时间都久,我拿头去改?
  2. 升级成本: 把之前业务全用新语言写一遍,成本过于高。
  3. 开发效率: xxx语言开发的框架完美的适应现在的业务,为啥要换新的?
  4. 学不动了: 刚出来a框架,又出了b,c,d 框架疯狂内卷,业务并没有增加多少。
  5. 新东西: Java刚写完,听说Go挺快转Go吧。总共一天交易10多笔,何必呢。
  6. 不敢动: 这段代码千万不要改,祖传的、我也不敢动。你和代码一个能跑,不怕死那就跑吧。

操作系统执行

在操作系统里面,CPU管理任务的调度、资源的分配和管理,硬件,内存等等。软件只是在操作系统上面跑的一个运用而已。

对于目前的操作系统或者是编程语言,大概都是按基本的规则进行资源的分配。下面介绍几种典型的语言,让我们知道语言的基础处理并发的方式。

  1. 以Java为例的多线程语言类:一般是一个进程,若干个线程。如果没有明确的协同机制,那么每个线程将独立运行,共享着进程的内存及CPU资源,多进程多线程之间虽然让多任务并行处理的能力大大提升。当然,每个线程也是要消耗相应的资源的,虽然它比进程要的资源少。
  2. 以JavaScript为例子的单进程异步IO语言类:一般是一个进程,单线程去处理任务。但是IO一般都是多线程的,遇上IO时,通过底层回调的形式把下一个任务拿来执行。
  3. 以Go为代表的多协程:一般是一个进程,单个线程有多个协程,减少了上线文的切换和锁的抢占,其实其他语言也有协程的概念,例如:C/C++。

语言和操作系统.png

程序和内核的交互

为什么要知道程序和内核的交互呢?因为你只有知道执行代码和内核的交互,你才能理解上面讲的多线程,异步IO,多协程,它是为啥要搞这样一出。

  1. 进程的调度

image.png

单核的 CPU 一次只能执行一个任务,想要实现多任务,需要把 CPU 的运行时间切成一段一段的时间片,每个时间片运行一个程序,循环的分配时间片给不同的应用程序,由于时间片非常的短,在用户看来,就像是多个任务同时在运行。

image.png

所以对于单核的CPU来说,任务的执行在某一刻,只可能有一个任务在执行任务

  1. 用户态与内核态
  • 内核态:cpu可以访问内存的所有数据,包括外围设备,例如硬盘,网卡,cpu也可以将自己从一个程序切换到另一个程序
  • 用户态:只能受限的访问内存,且不允许访问外围设备,占用cpu的能力被剥夺,cpu资源可以被其他程序获取
  1. 异步IO和同步IO

同步IO的模式:

image.png

异步IO的模式:

image.png

懂了这个底层,其他语言基本都不能说差不多,比较类似,剩下的语法问题、语言的坑、相关组件、生态相关这个没有办法,没有实际去开发很难清楚里面的细节。

代码简洁

  • 代码注释
// Find student from lists, with the given id
const student = students.find(s => s.id === id)

需要注释的有意义,没有意义的增加废话

  • 条件
if (kind === 'Persian' || kind === 'Maine' || kind === 'British Shorthair') {
	// do something ...
}

建议写法:

const CATS_TYPE = ['Persian', 'Maine', 'British Shorthair']

if (CATS_TYPE.includes(kind)) {
	// do something ...
}
  • 谨慎命名 给函数和变量取个好名字是优秀程序员的基本功,取名的基本要求是 名副其实见文知意。如果名称需要注释来补充,那就不算是个好名字。
var d // 日期

为什么不写成这样呢?注释并不会在外面显示。

var date

address 字段可能后面业务演变成 => detailAdress、smallAddress、anotherAddress

  • 函数和类 单一权责原则:在面向对象编程领域中,单一权责原则(Single responsibility principle)规定每个类都应该有一个单一的功能,并且该功能应该由这个类完全封装起来。一个类或者模块应该有且只有一个改变的原因。

  • 入参尽量是只是自己用到的

如果只有一个简单的参数能用的,那么尽量使用简单的参数,使函数更加的健壮性。 ZgmAXsoUNX.png

  • 良好的格式

把自己的代码当成诗去写,后面的人不忍心去糟蹋你的心血。

image.png

由于 Java 内部模型,会导致并发的问题。会导致变量非常容易被读成其他线程写入的值。

在并发300次,的情况下来看js 和 java并发的一段代码:

js 是单线程,只会有一个线程处理,那么变量永远只有一个线程去更新。 image.png

java 多线程去请求,那么变量被多个线程去更新,一个线程读到了其他线程修改数字的值。 image.png

JAVA 里面的JVM 模型

image.png

懂了node的单线程异步IO的java的多线程同步IO,对后面的学习和认知上会有很大的提升。