当前位置: 首页 > news >正文

golang常见面试题

1. go语言有哪些优点、特性?

语法简便,容易上手。

支持高并发,go有独特的协程概念,一般语言最小的执行单位是线程,go语言支持多开协程,协程是用户态线程,协程的占用内存更少,协程只独有自己的栈等一些资源。其他都是共享线程的。调度时可以极大减少上下文切换。

2. go的包管理

golang在1.11版本之前用的是GOPATH,项目代码要放在GOPATH/src目录下才可运行。但是GOPATH存在弊端,没有版本控制概念,go get的外部库,自己都不知道下载的什么版本,再多人协作开发时无法确定大家的外部库版本是否一致,会出大问题。

golang1.11后推荐使用go mod 管理,go env 下设置 GO111MODULE = on 打开。支持依赖升降级。


3. make和new 的一些区别

new 可以初始化声明所有类型,返回的是一个指针类型。对应的是该类型的空值

make 只能用来初始化 map slice channel 的,返回的就是这个类型。对应的是该类型的零值

new的用法不常见,一般使用 var 或 :=


4. channel 是可以被 close 的,之后还可以读写吗?

不管是有无缓冲channel。关闭后都可以读,读的是channel 传输类型的 零值。

不管是有无缓冲channel,关闭后都不可以写,写会panic


5. channel有什么用

channel 用来做协程之间的通信。go语言提倡不要用共享内存来通信,要用通信的方式来共享内存。channel就是利用通信的方式实现对资源的访问。

无缓冲channel可以用来做协程间的同步

有缓冲channel可以用来做消息队列

6. channel的底层结构?接收、发送消息的过程?

channel底层是一个结构体,里面包含一个环形缓冲区,还有接收等待队列和发送等待队列。分别存放等待写消息的协程队列和读消息的协程队列,还有一个互斥锁,用来保证channel的线程安全,防止多个协程并发读写。

当一个协程向channel写数据,如果是无缓冲通道,会将其加入到消息等待发送队列中,等待一个协程向channel读数据

读数据时,会先看缓冲区,如果没有再唤醒消息等待发送队列的第一个协程拿到信息,如果没有加入到消息等待接收队列,等待一个协程向channel写数据

7. channel 并发安全吗?

channel并发安全,底层结构体中有一个互斥锁,在并发环境下可以自动实现加锁解锁操作。


8. 怎么样输出一个有序的map

用slice存放map的key值,对slice进行排序,然后按照slice顺序查找map key value

用golang的数据结构 list来实现,list是一个链表。map[key]value value存放链表节点,写入map的时候同时按照顺序写入list中,顺序遍历时,只需要遍历链表即可。可以达到有序效果。


9. map在传参时的类型

golang传参都是值传递,只是对于map chan 等类型,他们在进行值拷贝的时候,调用的makechan 和 makemap 方法返回的都是指针类型的变量。导致操作的其实是同一个内存。

10. 可以直接对map取地址吗?

对map可以取址,但是对于map的key value不能取址,map不支持这种操作,当某种条件达到后,map会做增量扩容或者等量扩容操作。这时候每个key 的地址都可能发生变化。因此获取map key  value地址的操作是无意义的。

11. map底层结构

map底层是一个结构体,hmap,hmap中包含 元素的个数,桶的个数,以及指向桶数组的指针,每一个桶是一个bucket,bucket在go中用的是 bmap结构体,每个bucket可以存放 8个键值对,哈希值低八位相同的键存入bucket时会将高八位存储在tophash数组里。data 区域存放的key-value数据是按照 keykeykey valuevaluevalue存放的,overflow指针指向下一个bucket桶,通过链表将所有冲突的键连接起来。

12. 哪些数据类型不能作为map里面的key,哪些可以,有没有什么评判标准?

无法比较的数据类型都不能作为map里面的key。

基本数据类型都可作为key,指针也可以,因为指针比较的是地址。 数组也可以,结构体也可以

不可比较 map slice function

13. map是并发安全的吗?怎么实现并发安全?

map不是并发安全的,底层结构体没有用互斥锁进行加锁解锁操作。

如何实现并发安全,1.map+读写锁 (推荐)   2.用sync.Map


14. sync.Map如何解决并发问题?

sync.Map底层结构体中嵌入了一个互斥锁。。。。


15. gmp模型(局部饥饿、全局饥饿、全局缓存队列等)

最开始的时候,大多用线程池,开一定量的线程,当有工作任务到来时,会拿出一个线程处理,但当因为发生系统调用而阻塞时,线程池中可工作的线程就少了,线程池的性能就降低了。于是有了GMP模型。

G是协程,用户态线程

本地队列:每个P都有本地队列,本地队列中存放的是G

全局队列:当本地队列都满了,新来的G会优先加入本地队列中,本地队列满了会把本地队列的一半加入到全局队列

M是工作线程,用来处理协程的

P是处理器,默认数量是内核数,M通过获取P来处理P中的G

15. go有了协程之后,那它的线程是怎么调度的?(GMP模型)M最多多少个?

有调度策略:线程正常情况下会和P绑定,处理P中的本地队列G,但当处理G时,由于系统调用导致阻塞时,会触发hand off,M会和 P 解绑,把P转移给其他的空闲M,如果没有就创建一个新的M处理。如果M将P中的队列G处理完了,就会从其他P的本地队列中偷取一半协程来运行,如果其他都没有,就会从全局队列中选择一批来处理。

M最多10000个,在初始化运行时会设置最大值。但因为M需要获取到P才能处理G,P的数量是很有限的,所以M不会很多。

16. 线程数量和什么有关系?线程数量是无限大的吗?

线程数量和程序运行时,设置的最大M有关,默认是10000,并且跟P有关系,因为M必须要拿到P才能处理G。而且如果线程处理的阻塞的G完成后,可能会被销毁。不能无限大


16. slice深度拷贝

copy方法时,或者append触发扩容机制时都是深度拷贝。拷贝的是数据本身,新创建的对象和源对象不共享内存,会另开辟一个新的内存地址,值修改时不会影响源对象值。

17. slice和数组有什么区别?

slice 结构体中包含了 一个指向底层数组的指针还有slice的长度及容量

数组无法扩容,切片可以动态追加

数组声明时需要指定长度,切片不需要

数组是值类型的,切片是引用类型的


18. slice如何扩容?

1.18版本之前,当切片容量1024之前,每次扩容都是原来数组的二倍,当切片容量到1024之后,每次扩容都是原数组1.25倍

1.18版本,觉得扩容比例一下从2变成1.25有些不平滑,于是调整扩容机制,在容量小于256时,是2倍扩容,当容量大于256时,增加 (原来容量+3*256)/4。逐渐接近1.25倍,更平滑


19. interface{}怎么用

interface{}可以用来实现多态和符合设计模式的原则 依赖倒转 面向接口编程。 写一个接口,里面有要实现的方法,定义一个结构体,实现接口中的方法,然后初始化时,声明一个接口对象并指向具体的结构体,这样实现了面向接口编程,解耦。

也可以用来做强制类型转换,断言。interface.(type)


20. 说一下go的继承

go中的继承是通过结构体嵌套实现的,子结构体嵌套父结构体。初始化子结构体后,就可以用父结构体的方法。


21. go中哪些变量是不能比较的

map slice function 


22. golang强类型,弱类型?

golang是强类型语言,不会隐式的进行数据类型的转换。在速度上可能略逊弱类型语言,但是严谨性又避免了不必要的错误


23. golang并发控制?

可以用 Sync.WaitGroup实现  WaitGroup有三个方法,Add,Done,Wait。用来控制计数器数量。

可以用channel实现,goroutine之间通过channel通信,如果多个goroutine都写入channel,这时候通过缓冲区就可以实现并发控制,当缓冲区满时,后面的goroutine的写操作会被阻塞。


24. 一个go-routine最小占多大内存空间?

2kb


25. context类型有哪些?Context的作用是什么?context如何实现cancel的?

context主要用来在协程间传递关闭信号、信息的。可以控制多级协程

空context、cancelCtx、valueCtx、timerCtx。cancelCtx可以用来做协程的断开操作。




27. 正常模式和饥饿模式?

针对于互斥锁的,Mutex。正常模式下请求锁的协程要按照先入先出顺序排队,以此被唤醒,唤醒后还要与新请求锁的协程进行竞争,因为新请求的协程有优势,他们正在CPU上运行或者数量比较多。新唤醒的协程很难获取到锁,于是又会加到队列头部,如果一个等待的协程超过1ms仍未获取到锁,就会进入到饥饿模式。

饥饿模式下,互斥锁所有权会直接从解锁的协程转移到队首的协程,并且新到达的协程不会尝试获取锁而是加到队列尾部。如果一个等待协程获取到锁并且满足下面两个条件只一,就会回到正常模式。是队列的最后一个协程,等待时间小于1ms。

正常模式有更好的性能,饥饿模式可以避免尾部延迟这种情况


28. 用Go实现一个死锁

死锁存在四个条件,互斥,占有且等待,循环等待,不可强占用

func main() {ch1 := make(chan int)ch2 := make(chan int)var x sync.WaitGroupx.Add(2)go func() {ch2 <- 1fmt.Println(<-ch1)x.Done()}()go func() {fmt.Println(<-ch2)ch1 <- 1x.Done()}()x.Wait()
}


29. gc的了解

gc是垃圾回收机制,为了对堆栈上使用完的对象及时回收。防止内存溢出。最初1.3版本之前使用的是标记清除法,GC时会暂停程序进行标记清楚操作。STW时间很长。为了优化STW,1.3版本后缩短了一些STW时间,回收对象的操作放在STW时间之外。1.5版本时为了降低STW的时间,使用三色标记法+插入/删除屏障实现。三色标记法是在GC开始时,从根节点开始遍历所有可达对象,第一次遍历到的对象置灰,第二次遍历到的对象置黑。当没有灰色对象是开始回收对象。但是这样存在问题,当新创建了一个白色对象时,被一个黑色对象引用了,此时会造成刚创建的对象也被回收。还有当删除一个对象时,但是后面的对象还想要使用,但是断掉后后面的对象也会被回收。针对这两种情况提出了两个设计原则,强三色不变式和弱三色不变式,强三色强调黑色对象不能引用白色对象。弱三色不变式强调当黑色对象引用白色对象是,要保证还有一个灰色对象引用白色对象。针对这两个原则,产出了插入屏障和删除屏障,插入屏障实现的是强三色不变式,当黑色对象引用白色对象时,会将白色对象变为灰色对象。删除屏障实现的是弱三色不变式,当删除灰色后面的白色对象,会把删除的白色对象置灰。当扫描完没有灰色对象后,会将栈对象置白,启用STW,从新扫描一遍栈上的可达节点,最终删掉白色对象。插入屏障仍然需要re-scan栈上的节点。删除屏障,删除效率低,这次要删除的对象要等下次才能删掉。于是1.8版本后,采用三色标记法+混合写屏障。混合写屏障结合了插入和删除屏障的优点,栈上的对象不启用GC,扫描时会将所有栈上对象和新建对象置黑,针对堆上对象,所有创建和删除的对象都置灰。体现的是变形的弱三色不变式。1.8版本极大减少了STW时间,但并不是完全没有,因为在GC三色标记法之前还要STW,开启辅助GC和写屏障,统计根对象的任务数量等。


30. 什么时候会触发 golang GC 呢?

手动触发:调用runtime.GC来手动触发

定期触发:最长两分钟触发一次GC

内存达到一定值:每当内存扩大一倍时启用GC


31. 内存泄漏

创建的资源没有正常释放造成内存一直占用。也无法被GC回收。内存泄漏一般是程序员申请资源后没有手动去释放资源,关闭通道,解锁等。

通过pprof工具排查

32. go里面声明一个变量,它是放在栈上还是堆上?

内存逃逸,局部变量从栈上逃逸到堆上发生了内存逃逸。 

对于指针类型,因为分配内存时不知道是否存在外部引用,于是就将内存分配在堆中,防止函数结束后局部变量被回收。

如果数据量太大,栈放不下就会逃逸到堆中

interface类型上调用方法,编译时不知道是如何实现的,就会放到堆中。


33. 子goroutine的panic会不会被父g捕获

panic只能捕获本协程内部的错误,无法捕获子协程的错误

34. defer的先后顺序

defer满足栈的结构,先入后出。

35. defer什么情况下可以修改函数的返回值?

defer和return知识,return分为两步操作,第一步先将返回值赋给return,在准备返回之前要执行defer函数,执行完后才将结果返回。 如果定义了具名返回值,并且在defer时对这个变量进行了处理。那return 这个变量时就会修改。


36. golang 如何做超时控制?

1.timeAfter 这个函数会返回一个通道,并且过一段时间后会自动向通道发送一个数据。

2.context 的 withTimeout 和 withDeadline 方法,当到规定时间或超过某一时间后,会调用cancel方法来关闭channel。可以做超时控制


37. select 一般使用在什么场景

select一般与通道连用,用来监听多个通道的状态。

可以在多个通道中选择一个可用的操作来执行,如果没有一个通道准备就绪,select会执行defaule语句或者继续等待。

38.go程序运行顺序?

从main包开始执行,首先会导入引用的包,如果这个包里有init函数,会先执行这个包的init函数。

如果在main包定义了init函数,Go运行会在包导入后,全局变量初始化之前调用init函数。

调用之后会进行全局变量初始化操作,最终进入到main函数,是整个程序入口点。main函数执行后,程序会按照调用函数顺序依次执行其他函数。
 

相关文章:

golang常见面试题

1. go语言有哪些优点、特性&#xff1f; 语法简便&#xff0c;容易上手。 支持高并发&#xff0c;go有独特的协程概念&#xff0c;一般语言最小的执行单位是线程&#xff0c;go语言支持多开协程&#xff0c;协程是用户态线程&#xff0c;协程的占用内存更少&#xff0c;协程只…...

探索Python编程世界:从入门到精通

一.Python 从入门到精通 随着计算机科学的发展&#xff0c;编程已经成为了一种必备的技能。而 Python 作为一种简单易学、功能强大的编程语言&#xff0c;越来越受到人们的喜爱。本文将为初学者介绍 Python 编程的基础知识&#xff0c;帮助他们踏入 Python 编程的大门&#xf…...

Spark Shuffle Tracking 原理分析

Shuffle Tracking Shuffle Tracking 是 Spark 在没有 ESS(External Shuffle Service)情况&#xff0c;并且开启 Dynamic Allocation 的重要功能。如在 K8S 上运行 spark 没有 ESS。本文档所有的前提都是基于以上条件的。 如果开启了 ESS&#xff0c;那么 Executor 计算完后&a…...

Docker 干货系列 (持续更新)

dive 直接用本地镜像名称来启动&#xff0c;不需要走 hub dive.sh IMAGE_NAME"${1}" TMP_FILE/tmp/dive-tmp-image.tar docker save "$IMAGE_NAME" > $TMP_FILE && dive $TMP_FILE --sourcedocker-archive && rm $TMP_FILE示例&#…...

一.jwt token 前后端的逻辑

摘要 jwt token 前后端的交互逻辑&#xff0c;此部分只描述了一些交互逻辑&#xff0c;不涉及到真实应用的开发。 token的格式 tokenheader‘.’payload‘.’sign 第一次登陆的时候 判断http请求头中是否包含Authorization不包含则提示用户未登录当用户登录后&#xff0c;…...

day12_oop_抽象和接口

今日内容 零、 复习昨日 一、作业 二、抽象 三、接口 零、 复习昨日 final的作用 修饰类,类不能被继承修饰方法,方法不能重写[重点]修饰变量/属性,变成常量,不能更改 static修饰方法的特点 static修饰的方法,可以通过类名调用 static修饰的属性特点 在内存只有一份,被该类的所有…...

linux 将 api_key设置环境变量里

vi ~/.bashrc在最后添加api_key的环境变量 export GEMINI_API_KEYAIza**********WvpX7FwbdM刷新配置 source ~/.bashrc使用python 读取环境变量 import os gemini_api_key os.getenv(GEMINI_API_KEY) print(gemini_api_key)...

java八股文复习-----2024/03/03

1.接口和抽象类的区别 相似点&#xff1a; &#xff08;1&#xff09;接口和抽象类都不能被实例化 &#xff08;2&#xff09;实现接口或继承抽象类的普通子类都必须实现这些抽象方法 不同点&#xff1a; &#xff08;1&#xff09;抽象类可以包含普通方法和代码块&#x…...

UE4 Niagara 关卡3.4官方案例解析

Texture sampling is only supported on the GPU at the moment.(纹理采样目前仅在GPU上受支持) 效果&#xff1a;textures can be referenced within GPU particle systems。this demo maps a texture to a grid of particles&#xff08;纹理可以在GPU粒子系统中被引用这个演…...

C# Onnx segment-anything 分割万物 一键抠图

目录 介绍 效果 模型信息 sam_vit_b_decoder.onnx sam_vit_b_encoder.onnx 项目 代码 下载 C# Onnx segment-anything 分割万物 一键抠图 介绍 github地址&#xff1a;GitHub - facebookresearch/segment-anything: The repository provides code for running infere…...

Linux配置网卡功能

提示:工具下载链接在文章最后 目录 一.network功能介绍二.配置network功能2.1 network_ip配置检查 2.2 network_br配置2.2.1 配置的网桥原先不存在检查2.2.2 配置的网桥已存在-修改网桥IP检查2.2.3 配置的网桥已存在-只添加网卡到网桥里检查 2.3 network_bond配置检查 2.4 netw…...

【C++】十大排序算法之 归并排序 快速排序

本次介绍内容参考自&#xff1a;十大经典排序算法&#xff08;C实现&#xff09; - fengMisaka - 博客园 (cnblogs.com) 排序算法是《数据结构与算法》中最基本的算法之一。 十种常见排序算法可以分为两大类&#xff1a; 比较类排序&#xff1a;通过比较来决定元素间的相对次序…...

x-pack的破解方式和免费jar包!!可直接用!!

原理介绍 我们平时为es安装x-pack组件&#xff0c;用elasticsearch-plugin install x-pack &#xff0c;安装成功后。 1.cd $es目录/pulgins/x-pack 里面有一个x-pack-5.6.2.jar &#xff0c;将jar包反编译&#xff0c;然后将里面的licence的程序改下。再编译成jar包。 2…...

最新版本,Midjourney保姆级教程!

一、认识Midjourney 1.1、MidJourney是什么&#xff1f; 随着ChatGPT的横空出世&#xff0c;人类正式迈入AI元年&#xff0c;其中MidJourney便是AI绘图工具&#xff0c;它能根据用户输入的文字描述&#xff08;提示词&#xff09;生成绘画作品&#xff0c;不管是灵动的人物&a…...

Android中的几种定位方式调用详解

目前&#xff0c;移动端大致通过三种方式来进行设备定位&#xff1a;GPS、基站、wifi。本文就详细的讲解一下这几种定位方式和实现方法。 前言 android中我们一般使用LocationManager来获取位置信息&#xff0c;这里面有四中provider&#xff1a; public static final Strin…...

【软件测试】接口调不通排查分析+常遇面试题总结

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、接口调不通&am…...

c++基础学习第三天(指针,结构体)

c基础学习第三天&#xff08;指针&#xff0c;结构体&#xff09; 文章目录 1、指针1.1、指针的基本概念1.2、指针变量的定义和使用1.3、 指针所占内存空间1.4、空指针和野指针1.5、 const修饰指针1.5.1、const修饰指针-常量指针1.5.2、const修饰常量-指针常量1.5.3、const即修…...

【数仓】zookeeper软件安装及集群配置

相关文章 【数仓】基本概念、知识普及、核心技术【数仓】数据分层概念以及相关逻辑【数仓】Hadoop软件安装及使用&#xff08;集群配置&#xff09;【数仓】Hadoop集群配置常用参数说明 一、环境准备 准备3台虚拟机 Hadoop131&#xff1a;192.168.56.131Hadoop132&#xff…...

Qt 实现橡皮擦拭显示图片

1.简介 在一些游戏中看见类似解密破案的效果&#xff0c;使用手触摸去擦拭图片上的灰尘&#xff0c;然后显示最终的图片&#xff0c;所以也想试试Qt实现的效果。大家有自己想做的效果&#xff0c;都可以尝试。 以下是效果展示图。 可以控制橡皮擦的大小&#xff0c;进行擦拭…...

Vue3+Element-Plus中ELMessage样式丢失处理

Vu3Element-Plus项目中,element-plus使用按需引入有时会出现样式失效和在vscode中使用会报错[找不到名称“ElMessage”。ts(2304)]错误 ELMessage弹框样式丢失处理方法 使用按需引入就不能手动再引入 import { ElMessage } from "element-plus";ElMessage.success…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

Webpack性能优化:构建速度与体积优化策略

一、构建速度优化 1、​​升级Webpack和Node.js​​ ​​优化效果​​&#xff1a;Webpack 4比Webpack 3构建时间降低60%-98%。​​原因​​&#xff1a; V8引擎优化&#xff08;for of替代forEach、Map/Set替代Object&#xff09;。默认使用更快的md4哈希算法。AST直接从Loa…...

Linux nano命令的基本使用

参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时&#xff0c;显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

node.js的初步学习

那什么是node.js呢&#xff1f; 和JavaScript又是什么关系呢&#xff1f; node.js 提供了 JavaScript的运行环境。当JavaScript作为后端开发语言来说&#xff0c; 需要在node.js的环境上进行当JavaScript作为前端开发语言来说&#xff0c;需要在浏览器的环境上进行 Node.js 可…...