• 关于 编译器结构如何安装 的搜索结果

回答

转自:思否 本文作者:Michael van der Gulik 原文链接:《Why WebAssembly is a big deal》 译者:敖小剑 WebAssembly 是每个程序员都应该关注的技术。WebAssembly 会变得更流行。 WebAssembly 将取代 JavaScript。WebAssembly 将取代 HTML 和 CSS。 WebAssembly 将取代手机应用。WebAssembly 将取代桌面应用。在 10 年内,我保证每个程序员至少需要知道如何使用工具来操作 WebAssembly 并理解它是如何工作的。 你可能会说,“太离谱了!” 好吧,请继续阅读。 什么是 WebAssembly 当前形式的 WebAssembly 是 Web 浏览器的新扩展,可以运行预编译代码…快速地。在 C ++ 中编写了一些小代码,然后使用 Emscripten 编译器将该代码编译为 WebAssembly。通过一些 Javascript 粘合,就可以在 Web 浏览器中调用这一小段代码,例如,运行粒子模拟。 WebAssembly 文件,扩展名为.wasm,本身是包含可执行指令的二进制格式。要使用该文件,必须编写一个运行某些 Javascript 的 HTML 文件来获取、编译和执行 WebAssembly 文件。WebAssembly 文件在基于堆栈的虚拟机上执行,并使用共享内存与其 JavaScript 包装器进行通信。 到目前为止,这似乎并不有趣。它看起来只不过是 JavaScript 的加速器。但是,聪明的读者会对 WebAssembly 可能成为什么有所了解。 WebAssembly 将成为什么? 第一个重要发现是 WebAssembly 是一个安全的沙盒虚拟机。可以从 Internet 运行喜欢的 WebAssembly 代码,而确保它不会接管 PC 或服务器。四个主流 Web 浏览器对它的安全性非常有信心,它已经默认实现并启用了。它的真正安全性还有待观察,但安全性是 WebAssembly 的核心设计目标。 第二个重要发现是 WebAssembly 是一个通用的编译目标。它的原始编译器是一个 C 编译器,这个编译器很好地指示了 WebAssembly 虚拟机的低级和可重定向性。许多编程语言都使用 C 语言编写虚拟机,其他一些语言甚至使用 C 本身作为编译目标。 此时,有人整理了一个可以编译为 WebAssembly 的编程语言列表。这份名单将在未来很多年中继续增长。 WebAssembly 允许使用任何编程语言编写代码,然后让其他人在任何平台上安全地运行该代码,无需安装任何内容。朋友们,这是美好梦想的开始。 部署问题 我们来谈谈如何将软件提供给用户。 为新项目选择编程语言的一个重要因素是如何将项目部署到客户。您的程序员喜欢用 Haskell,Python,Visual Basic 或其他语言编写应用程序,具体取决于他们的喜好。要使用喜欢的语言,他们需要编译应用,制作一些可安装的软件包,并以某种方式将其安装在客户端的计算机上。有许多方法可以提供软件 - 包管理器,可执行安装程序或安装服务,如 Steam,Apple App Store,Google Play 或 Microsoft store。 每一个安装机制都意味着痛苦,从应用商店安装时的轻微疼痛,到管理员要求在他的 PC 上运行一些旧的 COBOL 代码时的集群头痛。 部署是一个问题。对于开发人员和系统管理员来说,部署一直是一个痛点。我们使用的编程语言与我们所针对的平台密切相关。如果大量用户在 PC 或移动设备上,我们使用 HTML 和 Javascript。如果用户是 Apple 移动设备用户,我们使用……呃…… Swift?(我实际上不知道)。如果用户在 Android 设备上,我们使用 Java 或 Kotlin。如果用户在真实计算机上并且愿意处理掉他们的部署问题,那么我们开发人员才能在我们使用的编程语言中有更多选择。 WebAssembly 有可能解决部署问题。 有了 WebAssembly,您可以使用任何编程语言编写应用,只要这些编程语言可以支持 WebAssembly,而应用可以在任何设备和任何具有现代 Web 浏览器的操作系统上运行。 硬件垄断 想购买台式机或笔记本电脑。有什么选择?好吧,有英特尔,有 AMD。多年来一直是双寡头垄断。保持这种双寡头垄断的一个原因是 x86 架构只在这两家公司之间交叉许可,而且通常预编译的代码需要 x86 或 x86-64(也就是 AMD-64)架构。还有其他因素,例如设计世界上最快的 CPU 是一件很艰难但也很昂贵的事情。 WebAssembly 是一种可让您在任何平台上运行代码的技术(之一)。如果它成为下一个风口,硬件市场将变得商品化。应用编译为 WebAssembly,就可以在任何东西上运行 - x86,ARM,RISC-V,SPARC。即便是操作系统市场也会商品化;您所需要的只是一个支持 WebAssembly 的浏览器,以便在硬件可以运行时运行最苛刻的应用程序。 编者注:Second State 研发的专为服务端优化的 WebAssembly 引擎 SSVM 已经可以运行在高通骁龙芯片上。Github 链接:https://github.com/second-sta... 云计算 但等等,还有更多。云计算成为IT经理办公室的流行词已有一段时间,WebAssembly 可以直接迎合它。 WebAssembly 在安全沙箱中执行。可以制作一个容器,它可以在服务器上接受和执行 WebAssembly 模块,而资源开销很小。对于提供的每个服务,无需在虚拟机上运行完整的操作系统。托管提供商只提供对可以上传代码的WebAssembly 容器的访问权限。它可以是一个原始容器,接收 socket 并解析自己的 HTTP 连接,也可以是一个完整的 Web 服务容器,其中 WebAssembly 模块只需要处理预解析的HTTP请求。 这还不存在。如果有人想变得富有,那么可以考虑这个想法。 编者注:目前已经有人正在实现这个想法,Byte Alliance 计划将WebAssembly 带到浏览器之外,Second State 已经发布了为服务端设计的WebAssembly 引擎开发者预览版。 不是云计算 WebAssembly 足以取代 PC 上本地安装的大多数应用程序。我们已经使用 WebGL(又名OpenGL ES 2.0)移植了游戏。我预测不久之后,受益于WebAssembly,像 LibreOffice 这样的大型应用可以直接从网站上获得,而无需安装。 在这种情况下,在本地安装应用没什么意义。本地安装的应用和 WebAssembly 应用之间几乎没有区别。WebAssembly 应用已经可以使用屏幕,键盘和鼠标进行交互。它可以在 2D 或 OpenGL 中进行图形处理,并使用硬件对视频流进行解码。可以播放和录制声音。可以访问网络摄像头。可以使用 WebSockets。可以使用 IndexedDB 存储大量数据在本地磁盘上。这些已经是 Web 浏览器中的标准功能,并且都可以使用 JavaScript 向 WebAssembly 暴露。 目前唯一困难的地方是 WebAssembly 无法访问本地文件系统。好吧,可以通过 HTML 使用文件上传对话,但这不算。最终,总会有人为此创建 API,并可能称之为 “WASI”。 “从互联网上运行应用程序!?胡说八道!“,你说。好吧,这是使用 Qt 和 WebAssembly 实现的文本编辑器 (以及更多)。 这是一个简单的例子。复杂的例子是在 WebBrowser 中运行的 Adobe Premier Pro 或 Blender。或者考虑像 Steam 游戏一样可以直接从网络上运行。这听起来像小说,但从技术上说这并非不能发生。 它会来的。 让我们裸奔! 目前,WebAssembly 在包含 HTML 和 Javascript 包装器的环境中执行。为什么不脱掉这些?有了 WebAssembly,为什么还要在浏览器中包含 HTML 渲染器和 JavaScript 引擎? 通过为所有服务提供标准化 API,这些服务通常是 Web 浏览器提供的,可以创建裸 WebAssembly。就是没有 HTML和 Javascript 包装来管理的 WebAssembly。访问的网页是 .wasm 文件,浏览器会抓取并运行该文件。浏览器为WebAssembly 模块提供画布,事件处理程序以及对浏览器提供的所有服务的访问。 这目前还不存在。如果现在使用 Web 浏览器直接访问 .wasm 文件,它会询问是否要下载它。我假设将设计所需的 API 并使其工作。 结果是 Web 可以发展。网站不再局限于 HTML,CSS 和 Javascript。可以创建全新的文档描述语言。可以发明全新的布局引擎。而且,对于像我这样的 polyglots 最相关,我们可以选择任何编程语言来实现在线服务。 可访问性 但我听到了强烈抗议!可访问性怎么样??搜索引擎怎么办? 好吧,我还没有一个好的答案。但我可以想象几种技术解决方案。 一个解决方案是我们保留内容和表现的分离。内容以标准化格式编写,例如 HTML。演示文稿由 WebAssembly 应用管理,该应用可以获取并显示内容。这允许网页设计师使用想要的任何技术进行任意演示 - 不需要 CSS,而搜索引擎和需要不同类型的可访问性的用户仍然可以访问内容。 请记住,许多 WebAssembly 应用并不是可以通过文本访问的,例如游戏和许多应用。盲人不会从图像编辑器中获得太多好处。 另一个解决方案是发明一个 API,它可以作为 WebAssembly 模块,来提供想在屏幕上呈现的 DOM,供屏幕阅读器或搜索引擎使用。基本上会有两种表示形式:一种是在图形画布上,另一种是产生结构化文本输出。 第三种解决方案是使用屏幕阅读器或搜索引擎可以使用的元数据来增强画布。执行 WebAssembly 并在画布上呈现内容,其中包含描述渲染内容的额外元数据。例如,该元数据将包括屏幕上的区域是否是菜单以及存在哪些选项,或者区域是否想要文本输入,以及屏幕上的区域的自然排序(也称为标签顺序)是什么。基本上,曾经在 HTML 中描述的内容现在被描述为具有元数据的画布区域。同样,这只是一个想法,它可能在实践中很糟糕。 可能是什么 1995年,Sun Microsystems 发布了 Java,带有 Java applets 和大量的宣传。有史以来第一次,网页可以做一些比 和 GIF 动画更有趣的事情。开发人员可以使应用完全在用户的 Web 浏览器中运行。它们没有集成到浏览器中,而是实现为繁重的插件,需要安装整个 JVM。1995年,这不是一个小的安装。applets 也需要一段时间来加载并使用大量内存。我们现在凭借大量内存,这不再是一个问题,但在 Java 生命的第一个十年里,它让体验变得令人厌烦。 applets 也不可靠。无法保证它们会运行,尤其是在用户使用 Microsoft 的实现时。他们也不安全,这是棺材里的最后一颗钉子。 以 JVM 为荣,其他语言最终演变为在 JVM 上运行。但现在,那艘船航行了。 FutureSplash / Macromedia / Adobe Flash 也是一个竞争者,但是是专有的,具有专有工具集和专有语言的专有格式。我读到他们确实在2009年开启了文件格式。最终从浏览器中删除了支持,因为它存在安全风险。 这里的结论是,如果希望您的技术存在于每个人的机器上,那么安全性就需要正视。我真诚地希望 WebAssembly 作为标准对安全问题做出很好的反应。 需要什么? WebAssembly 仍处于初期阶段。它目前能很好的运行代码,而规范版本是 1.0,二进制格式定型。目前正在开展SIMD 指令支持。通过 Web Workers 进行多线程处理也正在进行中。 工具可用,并将在未来几年不断改进。浏览器已经让你窥视 WebAssembly 文件。至少 Firefox 允许查看WebAssembly 字节码,设置断点并查看调用堆栈。我听说浏览器也有 profiling 支持。 语言支持包括一套不错的语言集合–C,C++和Rust是一流的公民。C#,Go和Lua显然有稳定的支持。Python,Scala,Ruby,Java和Typescript都有实验性支持。这可能是一个傲慢的陈述,但我真的相信任何想要在21世纪存在的语言都需要能够在 WebAssembly 上编译或运行。 在访问外部设备的 API 支持方面,我所知道的唯一可用于裸 WebAssembly 的 API 是 WASI,它允许文件和流访问等核心功能,允许 WebAssembly 在浏览器外运行。否则,任何访问外部世界的 API 都需要在浏览器中的 Javascript 中实现。除了本地机器上的文件访问,打印机访问和其他新颖的硬件访问(例如非标准蓝牙或USB设备)之外,应用所需的一切几乎都可以满足。“裸WebAssembly”并不是它成功的必要条件; 它只是一个小的优化,不需要浏览器包含对 HTML,CSS 或 Javascript 的支持。 我不确定在桌面环境中让 WebAssembly 成为一等公民需要什么。需要良好的复制和粘贴支持,拖放支持,本地化和国际化,窗口管理事件以及创建通知的功能。也许这些已经可以从网络浏览器中获得; 我经常惊讶与已经可能的事情。 引发爆炸的火花是创建允许现有应用移植的环境。如果创造了“用于 WebAssembly 的 Linux 子系统”,那么可以将大量现有的开源软件移植到 WebAssembly 上。它需要模拟一个文件系统 - 可以通过将文件系统的所有只读部分都缓存为 HTTP 请求来完成,并且所有可写部分都可以在内存中,远程存储或使用浏览器可以提供的任何文件访问。图形支持可以通过移植 X11 或 Wayland 的实现来使用 WebGL(我理解已经作为 AIGLX 存在?)。 一些 SDL 游戏已经被移植到 WebAssembly - 最着名的是官方演示。 一旦 JVM 在 WebAssembly 中运行,就可以在浏览器中运行大量的 Java 软件。同样适用于其他虚拟机和使用它们的语言。 与 Windows 软件的巨大世界一样,我没有答案。WINE 和 ReactOS 都需要底层的 x86 或 x86-64 机器,所以唯一的选择是获取源代码并移植它,或者使用 x86 模拟器。 尾声 WebAssembly 即将到来。 它来得很慢,但现在所有的部分都可以在你正在使用的浏览器上使用。现在我们等待构建用于从各种编程语言中定位 WebAssembly 的基础设施。一旦构建完成,我们将摆脱 HTML,CSS 和 Javascript 的束缚。 加入阿里云钉钉群享福利:每周技术直播,定期群内有奖活动、大咖问答 阿里云开发者社区

茶什i 2020-01-07 10:32:35 0 浏览量 回答数 0

问题

“木兰抄袭Python”官方致歉!从“红芯”到“木兰”,国产套壳何时休?

茶什i 2020-01-20 12:00:45 1642 浏览量 回答数 1

问题

【教程免费下载】深入理解计算机系统(英文版第3版)

玄学酱 2019-12-01 22:08:27 3332 浏览量 回答数 1

新用户福利专场,云服务器ECS低至102元/年

新用户专场,1核2G 102元/年起,2核4G 699.8元/年起

回答

相信对于很多Java开发来说,在刚刚接触Java语言的时候,就听说过Java是一门跨平台的语言,Java是平台无关性的,这也是Java语言可以迅速崛起并风光无限的一个重要原因。那么,到底什么是平台无关性?Java又是如何实现平台无关性的呢?本文就来简单介绍一下。 什么是平台无关性 平台无关性就是一种语言在计算机上的运行不受平台的约束,一次编译,到处执行(Write Once ,Run Anywhere)。 也就是说,用Java创建的可执行二进制程序,能够不加改变的运行于多个平台。 平台无关性好处 作为一门平台无关性语言,无论是在自身发展,还是对开发者的友好度上都是很突出的。 因为其平台无关性,所以Java程序可以运行在各种各样的设备上,尤其是一些嵌入式设备,如打印机、扫描仪、传真机等。随着5G时代的来临,也会有更多的终端接入网络,相信平台无关性的Java也能做出一些贡献。 对于Java开发者来说,Java减少了开发和部署到多个平台的成本和时间。真正的做到一次编译,到处运行。 平台无关性的实现 对于Java的平台无关性的支持,就像对安全性和网络移动性的支持一样,是分布在整个Java体系结构中的。其中扮演者重要的角色的有Java语言规范、Class文件、Java虚拟机(JVM)等。 编译原理基础 讲到Java语言规范、Class文件、Java虚拟机就不得不提Java到底是是如何运行起来的。 我们在Java代码的编译与反编译那些事儿中介绍过,在计算机世界中,计算机只认识0和1,所以,真正被计算机执行的其实是由0和1组成的二进制文件。 但是,我们日常开发使用的C、C++、Java、Python等都属于高级语言,而非二进制语言。所以,想要让计算机认识我们写出来的Java代码,那就需要把他"翻译"成由0和1组成的二进制文件。这个过程就叫做编译。负责这一过程的处理的工具叫做编译器。 在深入分析Java的编译原理中我们介绍过,在Java平台中,想要把Java文件,编译成二进制文件,需要经过两步编译,前端编译和后端编译: 前端编译主要指与源语言有关但与目标机无关的部分。Java中,我们所熟知的javac的编译就是前端编译。除了这种以外,我们使用的很多IDE,如eclipse,idea等,都内置了前端编译器。主要功能就是把.java代码转换成.class代码。 这里提到的.class代码,其实就是Class文件。 后端编译主要是将中间代码再翻译成机器语言。Java中,这一步骤就是Java虚拟机来执行的。 所以,我们说的,Java的平台无关性实现主要作用于以上阶段。如下图所示: 我们从后往前介绍一下这三位主演:Java虚拟机、Class文件、Java语言规范 Java虚拟机 所谓平台无关性,就是说要能够做到可以在多个平台上都能无缝对接。但是,对于不同的平台,硬件和操作系统肯定都是不一样的。 对于不同的硬件和操作系统,最主要的区别就是指令不同。比如同样执行a+b,A操作系统对应的二进制指令可能是10001000,而B操作系统对应的指令可能是11101110。那么,想要做到跨平台,最重要的就是可以根据对应的硬件和操作系统生成对应的二进制指令。 而这一工作,主要由我们的Java虚拟机完成。虽然Java语言是平台无关的,但是JVM确实平台有关的,不同的操作系统上面要安装对应的JVM。 上图是Oracle官网下载JDK的指引,不同的操作系统需要下载对应的Java虚拟机。 有了Java虚拟机,想要执行a+b操作,A操作系统上面的虚拟机就会把指令翻译成10001000,B操作系统上面的虚拟机就会把指令翻译成11101110。 ps:图中的Class文件中内容为mock内容 所以,Java之所以可以做到跨平台,是因为Java虚拟机充当了桥梁。他扮演了运行时Java程序与其下的硬件和操作系统之间的缓冲角色。 字节码 各种不同的平台的虚拟机都使用统一的程序存储格式——字节码(ByteCode)是构成平台无关性的另一个基石。Java虚拟机只与由字节码组成的Class文件进行交互。 我们说Java语言可以Write Once ,Run Anywhere。这里的Write其实指的就是生成Class文件的过程。 因为Java Class文件可以在任何平台创建,也可以被任何平台的Java虚拟机装载并执行,所以才有了Java的平台无关性。 Java语言规范 已经有了统一的Class文件,以及可以在不同平台上将Class文件翻译成对应的二进制文件的Java虚拟机,Java就可以彻底实现跨平台了吗? 其实并不是的,Java语言在跨平台方面也是做了一些努力的,这些努力被定义在Java语言规范中。 比如,Java中基本数据类型的值域和行为都是由其自己定义的。而C/C++中,基本数据类型是由它的占位宽度决定的,占位宽度则是由所在平台决定的。所以,在不同的平台中,对于同一个C++程序的编译结果会出现不同的行为。 举一个简单的例子,对于int类型,在Java中,int占4个字节,这是固定的。 但是在C++中却不是固定的了。在16位计算机上,int类型的长度可能为两字节;在32位计算机上,可能为4字节;当64位计算机流行起来后,int类型的长度可能会达到8字节。(这里说的都是可能哦!) 通过保证基本数据类型在所有平台的一致性,Java语言为平台无关性提供强了有力的支持。 小结 对于Java的平台无关性的支持是分布在整个Java体系结构中的。其中扮演着重要角色的有Java语言规范、Class文件、Java虚拟机等。 Java语言规范 通过规定Java语言中基本数据类型的取值范围和行为 Class文件 所有Java文件要编译成统一的Class文件 Java虚拟机 通过Java虚拟机将Class文件转成对应平台的二进制文件等 Java的平台无关性是建立在Java虚拟机的平台有关性基础之上的,是因为Java虚拟机屏蔽了底层操作系统和硬件的差异。 语言无关性 其实,Java的无关性不仅仅体现在平台无关性上面,向外扩展一下,Java还具有语言无关性。 前面我们提到过。JVM其实并不是和Java文件进行交互的,而是和Class文件,也就是说,其实JVM运行的时候,并不依赖于Java语言。 时至今日,商业机构和开源机构已经在Java语言之外发展出一大批可以在JVM上运行的语言了,如Groovy、Scala、Jython等。之所以可以支持,就是因为这些语言也可以被编译成字节码(Class文件)。而虚拟机并不关心字节码是有哪种语言编译而来的。详见牛逼了,教你用九种语言在JVM上输出HelloWorld 参考资料 《深入理解Java虚拟机(第二版)》 《深入Java虚拟机》 《Java语言规范——基于Java SE 8》 《Java虚拟机规范第8版》

montos 2020-06-01 15:54:00 0 浏览量 回答数 0

问题

PHP-SDK之如何实现安装?

青衫无名 2019-12-01 21:44:41 1582 浏览量 回答数 0

问题

2018python技术问答集锦,希望能给喜欢python的同学一些帮助

技术小能手 2019-12-01 19:31:10 2040 浏览量 回答数 2

问题

【精品问答】python百大常见问题与答案详解

祖安文状元 2020-02-24 17:56:41 363 浏览量 回答数 1

回答

在Java中,常量池的概念想必很多人都听说过。这也是面试中比较常考的题目之一。在Java有关的面试题中,一般习惯通过String的有关问题来考察面试者对于常量池的知识的理解,几道简单的String面试题难倒了无数的开发者。所以说,常量池是Java体系中一个非常重要的概念。 谈到常量池,在Java体系中,共用三种常量池。分别是字符串常量池、Class常量池和运行时常量池。 本文先来介绍一下到底什么是Class常量池。 什么是Class文件 在Java代码的编译与反编译那些事儿中我们介绍过Java的编译和反编译的概念。我们知道,计算机只认识0和1,所以程序员写的代码都需要经过编译成0和1构成的二进制格式才能够让计算机运行。 我们在《深入分析Java的编译原理》中提到过,为了让Java语言具有良好的跨平台能力,Java独具匠心的提供了一种可以在所有平台上都能使用的一种中间代码——字节码(ByteCode)。 有了字节码,无论是哪种平台(如Windows、Linux等),只要安装了虚拟机,都可以直接运行字节码。 同样,有了字节码,也解除了Java虚拟机和Java语言之间的耦合。这话可能很多人不理解,Java虚拟机不就是运行Java语言的么?这种解耦指的是什么? 其实,目前Java虚拟机已经可以支持很多除Java语言以外的语言了,如Groovy、JRuby、Jython、Scala等。之所以可以支持,就是因为这些语言也可以被编译成字节码。而虚拟机并不关心字节码是有哪种语言编译而来的。 Java语言中负责编译出字节码的编译器是一个命令是javac。 javac是收录于JDK中的Java语言编译器。该工具可以将后缀名为.java的源文件编译为后缀名为.class的可以运行于Java虚拟机的字节码。 如,我们有以下简单的HelloWorld.java代码: public class HelloWorld { public static void main(String[] args) { String s = "Hollis"; } } 通过javac命令生成class文件: javac HelloWorld.java 生成HelloWorld.class文件:  如何使用16进制打开class文件:使用 vim test.class ,然后在交互模式下,输入:%!xxd 即可。 可以看到,上面的文件就是Class文件,Class文件中包含了Java虚拟机指令集和符号表以及若干其他辅助信息。 要想能够读懂上面的字节码,需要了解Class类文件的结构,由于这不是本文的重点,这里就不展开说明了。 读者可以看到,HelloWorld.class文件中的前八个字母是cafe babe,这就是Class文件的魔数(Java中的”魔数”) 我们需要知道的是,在Class文件的4个字节的魔数后面的分别是4个字节的Class文件的版本号(第5、6个字节是次版本号,第7、8个字节是主版本号,我生成的Class文件的版本号是52,这时Java 8对应的版本。也就是说,这个版本的字节码,在JDK 1.8以下的版本中无法运行)在版本号后面的,就是Class常量池入口了。 Class常量池 Class常量池可以理解为是Class文件中的资源仓库。 Class文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池(constant pool table),用于存放编译器生成的各种字面量(Literal)和符号引用(Symbolic References)。 由于不同的Class文件中包含的常量的个数是不固定的,所以在Class文件的常量池入口处会设置两个字节的常量池容量计数器,记录了常量池中常量的个数。  当然,还有一种比较简单的查看Class文件中常量池的方法,那就是通过javap命令。对于以上的HelloWorld.class,可以通过 javap -v HelloWorld.class 查看常量池内容如下:  从上图中可以看到,反编译后的class文件常量池中共有16个常量。而Class文件中常量计数器的数值是0011,将该16进制数字转换成10进制的结果是17。 原因是与Java的语言习惯不同,常量池计数器是从0开始而不是从1开始的,常量池的个数是10进制的17,这就代表了其中有16个常量,索引值范围为1-16。 常量池中有什么 介绍完了什么是Class常量池以及如何查看常量池,那么接下来我们就要深入分析一下,Class常量池中都有哪些内容。 常量池中主要存放两大类常量:字面量(literal)和符号引用(symbolic references)。 字面量 前面说过,运行时常量池中主要保存的是字面量和符号引用,那么到底什么字面量? 在计算机科学中,字面量(literal)是用于表达源代码中一个固定值的表示法(notation)。几乎所有计算机编程语言都具有对基本值的字面量表示,诸如:整数、浮点数以及字符串;而有很多也对布尔类型和字符类型的值也支持字面量表示;还有一些甚至对枚举类型的元素以及像数组、记录和对象等复合类型的值也支持字面量表示法。 以上是关于计算机科学中关于字面量的解释,并不是很容易理解。说简单点,字面量就是指由字母、数字等构成的字符串或者数值。 字面量只可以右值出现,所谓右值是指等号右边的值,如:int a=123这里的a为左值,123为右值。在这个例子中123就是字面量。 int a = 123; String s = "hollis"; 上面的代码事例中,123和hollis都是字面量。 本文开头的HelloWorld代码中,Hollis就是一个字面量。 符号引用 常量池中,除了字面量以外,还有符号引用,那么到底什么是符号引用呢。 符号引用是编译原理中的概念,是相对于直接引用来说的。主要包括了以下三类常量: * 类和接口的全限定名 * 字段的名称和描述符 * 方法的名称和描述符 这也就可以印证前面的常量池中还包含一些com/hollis/HelloWorld、main、([Ljava/lang/String;)V等常量的原因了。 Class常量池有什么用 前面介绍了这么多,关于Class常量池是什么,怎么查看Class常量池以及Class常量池中保存了哪些东西。有一个关键的问题没有讲,那就是Class常量池到底有什么用。 首先,可以明确的是,Class常量池是Class文件中的资源仓库,其中保存了各种常量。而这些常量都是开发者定义出来,需要在程序的运行期使用的。 在《深入理解Java虚拟》中有这样的表述: Java代码在进行Javac编译的时候,并不像C和C++那样有“连接”这一步骤,而是在虚拟机加载Class文件的时候进行动态连接。也就是说,在Class文件中不会保存各个方法、字段的最终内存布局信息,因此这些字段、方法的符号引用不经过运行期转换的话无法得到真正的内存入口地址,也就无法直接被虚拟机使用。当虚拟机运行时,需要从常量池获得对应的符号引用,再在类创建时或运行时解析、翻译到具体的内存地址之中。关于类的创建和动态连接的内容,在虚拟机类加载过程时再进行详细讲解。 前面这段话,看起来很绕,不是很容易理解。其实他的意思就是: Class是用来保存常量的一个媒介场所,并且是一个中间场所。在JVM真的运行时,需要把常量池中的常量加载到内存中。 至于到底哪个阶段会做这件事情,以及Class常量池中的常量会以何种方式被加载到具体什么地方,会在本系列文章的后续内容中继续阐述。欢迎关注我的博客(http://www.hollischuang.com) 和公众号(Hollis),即可第一时间获得最新内容。 另外,关于常量池中常量的存储形式,以及数据类型的表示方法本文中并未涉及,并不是说这部分知识点不重要,只是Class字节码的分析本就枯燥,作者不想在一篇文章中给读者灌输太多的理论上的内容。感兴趣的读者可以自行Google学习,如果真的有必要,我也可以单独写一篇文章再深入介绍。 参考资料 《深入理解java虚拟机》 《Java虚拟机原理图解》 1.2.2、Class文件中的常量池详解(上)

montos 2020-06-02 10:12:18 0 浏览量 回答数 0

问题

TypeScript:拥有超能力的 JavaScript

茶什i 2020-01-20 15:15:47 3 浏览量 回答数 0

回答

Go 的优势在于能够将简单的和经过验证的想法结合起来,同时避免了其他语言中出现的许多问题。本文概述了 Go 背后的一些设计原则和工程智慧,作者认为,Go 语言具备的所有这些优点,将共同推动其成为接替 Java 并主导下一代大型软件开发平台的最有力的编程语言候选。很多优秀的编程语言只是在个别领域比较强大,如果将所有因素都纳入考虑,没有其他语言能够像 Go 语言一样“全面开花”,在大型软件工程方面,尤为如此。 基于现实经验 Go 是由经验丰富的软件行业老手一手创建的,长期以来,他们对现有语言的各种缺点有过切身体会的痛苦经历。几十年前,Rob Pike 和 Ken Thompson 在 Unix、C 和 Unicode 的发明中起到了重要作用。Robert Griensemer 在为 JavaScript 和 Java 开发 V8 和 HotSpot 虚拟机之后,在编译器和垃圾收集方面拥有数十年的经验。有太多次,他们不得不等待 Google 规模的 C++/Java 代码库进行编译。于是,他们开始着手创建新的编程语言,将他们半个世纪以来的编写代码所学到的一切经验包含进去。 专注于大型工程 小型工程项目几乎可以用任何编程语言来成功构建。当成千上万的开发人员在数十年的持续时间压力下,在包含数千万行代码的大型代码库上进行协作时,就会发生真正令人痛苦的问题。这样会导致一些问题,如下: 较长的编译时间导致中断开发。代码库由几个人 / 团队 / 部门 / 公司所拥有,混合了不同的编程风格。公司雇佣了数千名工程师、架构师、测试人员、运营专家、审计员、实习生等,他们需要了解代码库,但也具备广泛的编码经验。依赖于许多外部库或运行时,其中一些不再以原始形式存在。在代码库的生命周期中,每行代码平均被重写 10 次,被弄得千疮百痍,而且还会发生技术偏差。文档不完整。 Go 注重减轻这些大型工程的难题,有时会以使小型工程变得更麻烦为代价,例如,代码中到处都需要几行额外的代码行。 注重可维护性 Go 强调尽可能多地将工作转给自动化的代码维护工具中。Go 工具链提供了最常用的功能,如格式化代码和导入、查找符号的定义和用法、简单的重构以及代码异味的识别。由于标准化的代码格式和单一的惯用方式,机器生成的代码更改看起来非常接近 Go 中人为生成的更改并使用类似的模式,从而允许人机之间更加无缝地协作。 保持简单明了 初级程序员为简单的问题创建简单的解决方案。高级程序员为复杂的问题创建复杂的解决方案。伟大的程序员找到复杂问题的简单解决方案。 ——Charles Connell 让很多人惊讶的一点是,Go 居然不包含他们喜欢的其他语言的概念。Go 确实是一种非常小巧而简单的语言,只包含正交和经过验证的概念的最小选择。这鼓励开发人员用最少的认知开销来编写尽可能简单的代码,以便许多其他人可以理解并使用它。 使事情清晰明了 良好的代码总是显而易见的,避免了那些小聪明、难以理解的语言特性、诡异的控制流和兜圈子。 许多语言都致力提高编写代码的效率。然而,在其生命周期中,人们阅读代码的时间却远远超过最初编写代码所需的时间(100 倍)。例如,审查、理解、调试、更改、重构或重用代码。在查看代码时,往往只能看到并理解其中的一小部分,通常不会有完整的代码库概述。为了解释这一点,Go 将所有内容都明确出来。 错误处理就是一个例子。让异常在各个点中断代码并在调用链上冒泡会更容易。Go 需要手动处理和返回每个错误。这使得它可以准确地显示代码可以被中断的位置以及如何处理或包装错误。总的来说,这使得错误处理编写起来更加繁琐,但是也更容易理解。 简单易学 Go 是如此的小巧而简单,以至于人们可以在短短几天内就能研究通整个语言及其基本概念。根据我们的经验,培训用不了一个星期(相比于掌握其他语言需要几个月),初学者就能够理解 Go 专家编写的代码,并为之做出贡献。为了方便吸引更多的用户,Go 网站提供了所有必要的教程和深入研究的文章。这些教程在浏览器中运行,允许人们在将 Go 安装到本地计算机上之前就能够学习和使用 Go。 解决之道 Go 强调的是团队之间的合作,而不是个人的自我表达。 在 Go(和 Python)中,所有的语言特性都是相互正交和互补的,通常有一种方法可以做一些事情。如果你想让 10 个 Python 或 Go 程序员来解决同一个问题,你将会得到 10 个相对类似的解决方案。不同的程序员在彼此的代码库中感觉更自在。在查看其他人的代码时,国骂会更少,而且人们的工作可以更好地融合在一起,从而形成了一致的整体,人人都为之感到自豪,并乐于工作。这还避免了大型工程的问题,如: 开发人员认为良好的工作代码很“混乱”,并要求在开始工作之前进行重写,因为他们的思维方式与原作者不同。 不同的团队成员使用不同的语言子集来编写相同代码库的部分内容。 ![image.png](https://ucc.alicdn.com/pic/developer-ecology/e64418f1455d46aaacfdd03fa949f16d.png) 简单、内置的并发性 Go 专为现代多核硬件设计。 目前使用的大多数编程语言(Java、JavaScript、Python、Ruby、C、C++)都是 20 世纪 80 年代到 21 世纪初设计的,当时大多数 CPU 只有一个计算内核。这就是为什么它们本质上是单线程的,并将并行化视为边缘情况的马后炮。通过现成和同步点之类的附加组件来实现,而这些附加组件既麻烦又难以正确使用。第三方库虽然提供了更简单的并发形式,如 Actor 模型,但是总有多个可用选项,结果导致了语言生态系统的碎片化。今天的硬件拥有越来越多的计算内核,软件必须并行化才能高效运行。Go 是在多核处理器时代编写的,并且在语言中内置了简单、高级的 CSP 风格并发性。 面向计算的语言原语 就深层而言,计算机系统接收数据,对其进行处理(通常要经过几个步骤),然后输出结果数据。例如,Web 服务器从客户端接收 HTTP 请求,并将其转换为一系列数据库或后端调用。一旦这些调用返回,它就将接收到的数据转换成 HTML 或 JSON 并将其输出给调用者。Go 的内置语言原语直接支持这种范例: 结构表示数据 读和写代表流式 IO 函数过程数据 goroutines 提供(几乎无限的)并发性 在并行处理步骤之间传输管道数据 因为所有的计算原语都是由语言以直接形式提供的,因此 Go 源代码更直接地表达了服务器执行的操作。 OO — 好的部分 更改基类中的某些内容的副作用 面向对象非常有用。过去几十年来,面向对象的使用富有成效,并让我们了解了它的哪些部分比其他部分能够更好地扩展。Go 在面向对象方面采用了一种全新的方法,并记住了这些知识。它保留了好的部分,如封装、消息传递等。Go 还避免了继承,因为它现在被认为是有害的,并为组合提供了一流的支持。 现代标准库 目前使用的许多编程语言(Java、JavaScript、Python、Ruby)都是在互联网成为当今无处不在的计算平台之前设计的。因此,这些语言的标准库只提供了相对通用的网络支持,而这些网络并没有针对现代互联网进行优化。Go 是十年前创建的,当时互联网已全面发展。Go 的标准库允许在没有第三方库的情况下创建更复杂的网络服务。这就避免了第三方库的常见问题: 碎片化:总是有多个选项实现相同的功能。 膨胀:库常常实现的不仅仅是它们的用途。 依赖地狱:库通常依赖于特定版本的其他库。 未知质量:第三方代码的质量和安全性可能存在问题。 未知支持:第三方库的开发可能随时停止支持。 意外更改:第三方库通常不像标准库那样严格地进行版本控制。 关于这方面更多的信息请参考 Russ Cox 提供的资料 标准化格式 Gofmt 的风格没有人会去喜欢,但人人都会喜欢 gofmt。 ——Rob Pike Gofmt 是一种以标准化方式来格式化 Go 代码的程序。它不是最漂亮的格式化方式,但却是最简单、最不令人生厌的格式化方式。标准化的源代码格式具有惊人的积极影响: 集中讨论重要主题: 它消除了围绕制表符和空格、缩进深度、行长、空行、花括号的位置等一系列争论。 开发人员在彼此的代码库中感觉很自在, 因为其他代码看起来很像他们编写的代码。每个人都喜欢自由地按照自己喜欢的方式进行格式化代码,但如果其他人按照自己喜欢的方式格式化了代码,这么做很招人烦。 自动代码更改并不会打乱手写代码的格式,例如引入了意外的空白更改。 许多其他语言社区现在正在开发类似 gofmt 的东西。当作为第三方解决方案构建时,通常会有几个相互竞争的格式标准。例如,JavaScript 提供了 Prettier 和 StandardJS。这两者都可以用,也可以只使用其中的一个。但许多 JS 项目并没有采用它们,因为这是一个额外的决策。Go 的格式化程序内置于该语言的标准工具链中,因此只有一个标准,每个人都在使用它。 快速编译 ![image.png](https://ucc.alicdn.com/pic/developer-ecology/8a76f3f07f484266af42781d9e7b8692.png) 对于大型代码库来说,它们长时间的编译是促使 Go 诞生的原因。Google 主要使用的是 C++ 和 Java,与 Haskell、Scala 或 Rust 等更复杂的语言相比,它们的编译速度相对较快。尽管如此,当编译大型代码库时,即使是少量的缓慢也会加剧编译的延迟,从而激怒开发人员,并干扰流程。Go 的设计初衷是为了提高编译效率,因此它的编译器速度非常快,几乎没有编译延迟的现象。这给 Go 开发人员提供了与脚本类语言类似的即时反馈,还有静态类型检查的额外好处。 交叉编译 由于语言运行时非常简单,因此它被移植到许多平台,如 macOS、Linux、Windows、BSD、ARM 等。Go 可以开箱即用地为所有这些平台编译二进制文件。这使得从一台机器进行部署变得很容易。 快速执行 Go 的运行速度接近于 C。与 JITed 语言(Java、JavaScript、Python 等)不同,Go 二进制文件不需要启动或预热的时间,因为它们是作为编译和完全优化的本地代码的形式发布的。Go 的垃圾收集器仅引入微秒量级的可忽略的停顿。除了快速的单核性能外,Go 还可以轻松利用所有的 CPU 内核。 内存占用小 像 JVM、Python 或 Node 这样的运行时不仅仅在运行时加载程序代码,每次运行程序时,它们还会加载大型且高度复杂的基础架构,以进行编译和优化程序。如此一来,它们的启动时间就变慢了,并且还占用了大量内存(数百兆字节)。而 Go 进程的开销更小,因为它们已经完全编译和优化,只需运行即可。Go 还以非常节省内存的方式来存储数据。在内存有限且昂贵的云环境中,以及在开发过程中,这一点非常重要。我们希望在一台机器上能够快速启动整个堆栈,同时将内存留给其他软件。 部署规模小 Go 的二进制文件大小非常简洁。Go 应用程序的 Docker 镜像通常比用 Java 或 Node 编写的等效镜像要小 10 倍,这是因为它无需包含编译器、JIT,以及更少的运行时基础架构的原因。这些特点,在部署大型应用程序时很重要。想象一下,如果要将一个简单的应用程序部署到 100 个生产服务器上会怎么样?如果使用 Node/JVM 时,我们的 Docker 注册表就必须提供 100 个 docker 镜像,每个镜像 200MB,那么一共就需要 20GB。要完成这些部署就需要一些时间。想象一下,如果我们想每天部署 100 次的话,如果使用 Go 服务,那么 Docker 注册表只需提供 10 个 docker 镜像,每个镜像只有 20MB,共只需 2GB 即可。大型 Go 应用程序可以更快、更频繁地部署,从而使得重要更新能够更快地部署到生产环境中。 独立部署 Go 应用程序部署为一个包含所有依赖项的单个可执行文件,并无需安装特定版本的 JVM、Node 或 Python 运行时;也不必将库下载到生产服务器上,更无须对运行 Go 二进制文件的机器进行任何更改。甚至也不需要讲 Go 二进制文件包装到 Docker 来共享他们。你需要做的是,只是将 Go 二进制文件放到服务器上,它就会在那里运行,而不用关心服务器运行的是什么。前面所提到的那些,唯一的例外是使用net和os/user包时针对对glibc的动态链接。 供应依赖关系 Go 有意识避免使用第三方库的中央存储库。Go 应用程序直接链接到相应的 Git 存储库,并将所有相关代码下载(供应)到自己的代码库中。这样做有很多好处: 在使用第三方代码之前,我们可以对其进行审查、分析和测试。该代码就和我们自己的代码一样,是我们应用程序的一部分,应该遵循相同的质量、安全性和可靠性标准。 无需永久访问存储依赖项的各个位置。从任何地方(包括私有 Git repos)获取第三方库,你就能永久拥有它们。 经过验收后,编译代码库无需进一步下载依赖项。 若互联网某处的代码存储库突然提供不同的代码,这也并不足为奇。 即使软件包存储库速度变慢,或托管包不复存在,部署也不会因此中断。 兼容性保证 Go 团队承诺现有的程序将会继续适用于新一代语言。这使得将大型项目升级到最新版本的编译器会非常容易,并且可从它们带来的许多性能和安全性改进中获益。同时,由于 Go 二进制文件包含了它们需要的所有依赖项,因此可以在同一服务器上并行运行使用不同版本的 Go 编译器编译的二进制文件,而无需进行复杂的多个版本的运行时设置或虚拟化。 文档 在大型工程中,文档对于使软件可访问性和可维护性非常重要。与其他特性类似,Go 中的文档简单实用: 由于它是嵌入到源代码中的,因此两者可以同时维护。 它不需要特殊的语法,文档只是普通的源代码注释。 可运行单元测试通常是最好的文档形式。因此 Go 要求将它们嵌入到文档中。 所有的文档实用程序都内置在工具链中,因此每个人都使用它们。 Go linter 需要导出元素的文档,以防止“文档债务”的积累。 商业支持的开源 当商业实体在开放式环境下开发时,那么一些最流行的、经过彻底设计的软件就会出现。这种设置结合了商业软件开发的优势——一致性和精细化,使系统更为健壮、可靠、高效,并具有开放式开发的优势,如来自许多行业的广泛支持,多个大型实体和许多用户的支持,以及即使商业支持停止的长期支持。Go 就是这样发展起来的。 缺点 当然,Go 也并非完美无缺,每种技术选择都是有利有弊。在决定选择 Go 之前,有几个方面需要进行考虑考虑。 未成熟 虽然 Go 的标准库在支持许多新概念(如 HTTP 2 Server push 等)方面处于行业领先地位,但与 JVM 生态系统中的第三方库相比,用于外部 API 的第三方 Go 库可能不那么成熟。 即将到来的改进 由于清楚几乎不可能改变现有的语言元素,Go 团队非常谨慎,只在新特性完全开发出来后才添加新特性。在经历了 10 年的有意稳定阶段之后,Go 团队正在谋划对语言进行一系列更大的改进,作为 Go 2.0 之旅的一部分。 无硬实时 虽然 Go 的垃圾收集器只引入了非常短暂的停顿,但支持硬实时需要没有垃圾收集的技术,例如 Rust。 结语 本文详细介绍了 Go 语言的一些优秀的设计准则,虽然有的准则的好处平常看起来没有那么明显。但当代码库和团队规模增长几个数量级时,这些准则可能会使大型工程项目免于许多痛苦。总的来说,正是这些设计准则让 Go 语言成为了除 Java 之外的编程语言里,用于大型软件开发项目的绝佳选择。

有只黑白猫 2020-01-07 14:11:38 0 浏览量 回答数 0

问题

CrossApp的环境配置教程Windows&mac 1.Windows下环境配置 2.Mac:报错

kun坤 2020-06-07 22:55:51 0 浏览量 回答数 1

问题

CrossApp的环境配置教程Windows&mac 403.10 禁止访问:配置无效 

kun坤 2020-05-28 13:24:09 3 浏览量 回答数 1

问题

CrossApp的环境配置教程Windows&mac - 配置报错

montos 2020-05-31 19:53:59 0 浏览量 回答数 1

问题

使用Yeoman和Polymer创建Web应用:报错

kun坤 2020-06-08 11:03:09 3 浏览量 回答数 1

问题

Nginx性能为什么如此吊

小柒2012 2019-12-01 21:20:47 15038 浏览量 回答数 3

回答

作者:九章算法 链接:https://www.zhihu.com/question/22744854/answer/763206431 来源:知乎 首先,这个神仙项目请你pick: https://github.com/sindresorhus/awesome 各领域各语言资源大合集 另外,可以关注GitHub的每日榜单,看看大家都在关注些什么(虽然有国外小哥吐槽榜单上都是中文哈哈 https://github.com/trending/python?since=daily 推荐不同语言的几个项目: Python : youtube-dl这个程序是一个开源的python项目。支持MacOS、Linux和Windows平台,可以在官网直接下载编译好的程序。可以用来下载YouTube视频,国内的一些视频站也可以进行下载。 interview_internal_reference: 总结了2019年最新的阿里,腾讯,百度,美团,头条等技术面试题目以及答案,分析汇总。 sherlock: 高级机器视觉软件,可以用于广泛的自动化检测应用。它提供了最大的设计灵活性,丰富的已验证的工具和功能。 DeepFaceLab: 这是一个github上的开源项目,所有人都可以查看源代码也能免费使用。个人认为这个项目的最大优点就是安装超级简单,几乎是无需安装,使用过程也不复杂 Manim: 解释数学视频的动画引擎。可以用来创建精确的2D动画。 XSStrike:XSStrike是一个Cross Site Scripting检测套件,配备四个手写解析器,一个智能有效载荷生成器,一个强大的模糊引擎和一个非常快速的爬虫。 XSStrike不是像其他工具一样注入有效载荷并检查它的工作原理,而是通过多个解析器分析响应,然后通过与模糊引擎集成的上下文分析来保证有效载荷。 f="https://github.com/wangshub">Douyin -Bot:抖音机器人。是用于机器人算法的Python代码。教你如何在抖音上找到漂亮小姐姐~~ Photon:快速抓取工具,可以提取网址,电子邮件,文件,网站帐户等等。 google-images-download:可以实现搜索和下载数百个Google图像的Python脚本到本地。 faceswap是个基于dlib的换脸程序。模型训练速度较快,同样配置下更快的到达低loss值,而且有gui界面版本。 you-getyou-get 是py上一个方便的下载工具。这个爬虫神器能爬取视频网站和图片网站,你不用写任何代码就能很容易的把你喜欢的视频或者图片甚至音频文件给扒下来。而且支持腾讯、搜狐、新浪、B站、央视网、芒果TV,乐视网、优酷、熊猫斗鱼等等大多数的国内主流视频网站。 Java: advanced-java: Java工程师进阶知识扫盲,适合系统学习。 vhr:一个前后端分离的人力资源管理系统,采用SpringBoot+Vue开发。这个项目的权限管理模块已经开发完成,其他模块还在开发当中。可以管理角色和资源的关系,管理用户和角色的关系。 cat:作为服务端项目基础组件,cat提供了 Java, C/C++, Node.js, Python, Go 等多语言客户端,已经在美团点评的基础架构中间件框架(MVC框架,RPC框架,数据库框架,缓存框架等,消息队列,配置系统等)深度集成,为美团点评各业务线提供系统丰富的性能指标、健康状况、实时告警等。 jeecg-boot:一款基于代码生成器的JAVA快速开发平台!全新架构前后端分离:SpringBoot 2.x,Ant Design&Vue,Mybatis,Shiro,JWT。强大的代码生成器让前后端代码一键生成,无需写任何代码,绝对是全栈开发的福音!! interviews:软件工程技术面试个人指南。可以这里找到针对很多面试问题的视频解决方案以及详细说明。 p3c:是阿里巴巴p3c项目组进行研发。根据《阿里巴巴Java开发规范》转化而成的自动化插件,并且实现了部分自动编程。 SpringAll:包括了Spring Boot,Spring Boot&Shiro,Spring Cloud,Spring Boot&Spring Security&Spring Security OAuth2等系列教程。toBeTopJavaer:Java工程师成神之路。总结的很好,直接理解学习就完了。 JavaScript: quasar:Quasar Framework是MIT许可的开源项目。能在记录时间内构建高性能VueJS用户界面 Daily-Interview-Question:前端大厂面试题汇总 next.js:一个基于React的一个服务端渲染简约框架。它使用React语法,可以很好的实现代码的模块化,有利于代码的开发和维护。 javascript-algorithms:这个存储库包含许多流行算法和数据结构的基于JavaScript的示例。每个算法和数据结构都有自己独立的自述文件,包含相关说明和链接,供进一步阅读 baidu-netdisk-downloaderx:一款图形界面的百度网盘不限速下载器,支持Windows,Linux和Mac。重点在不限速! 其他好玩的项目~ ChineseBQB:国内表情包大集合~~ komeiji-satori/Dress:女装大佬项目,一张图你就懂了 chinese-poetry最全的中文诗歌古典文集数据库.包含5.5万首唐诗、26万首宋诗和2.1万首宋词。唐宋两朝近1.4万古诗人, 和两宋时期1千多位词人 thefuck该项目的主要作用是,在terminal 里输错命令之后无需修改,fuck 一下,自动帮你更正命令,既解气又实用。 加入阿里云钉钉群享福利:每周技术直播,定期群内有奖活动、大咖问答 阿里云开发者社区

茶什i 2020-01-08 10:37:26 0 浏览量 回答数 0

回答

redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类keyvalue存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Python,Ruby,Erlang,PHP客户端,使用很方便。问题是这个项目还很新,可能还不足够稳定, redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类keyvalue存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Python,Ruby,Erlang,PHP客户端,使用很方便。问题是这个项目还很新,可能还不足够稳定,而且没有在实际的一些大型系统应用的实例。此外,缺乏mc中批量get也是比较大的问题,始终批量获取跟多次获取的网络开销是不一样的。 性能测试结果: SET操作每秒钟 110000 次,GET操作每秒钟 81000 次,服务器配置如下: Linux 2.6, Xeon X3320 2.5Ghz. stackoverflow 网站使用 Redis 做为缓存服务器。 安装过程: Redis是一种高级key-value数据库。它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富。有字符串,链表,集 合和有序集合。支持在服务器端计算集合的并,交和补集(difference)等,还支持多种排序功能。所以Redis也可以被看成是一个数据结构服务 器。 Redis的所有数据都是保存在内存中,然后不定期的通过异步方式保存到磁盘上(这称为“半持久化模式”);也可以把每一次数据变化都写入到一个append only file(aof)里面(这称为“全持久化模式”)。 一、下载最新版 wget http://redis.googlecode.com/files/redis-2.0.0-rc4.tar.gz 二、解压缩 tar redis-2.0.0-rc4.tar.gz 三、安装C/C++的编译组件(非必须) apt-get install build-essential 四、编译 cd redis-2.0.0-rc4 make make命令执行完成后,会在当前目录下生成本个可执行文件,分别是redis-server、redis-cli、redis-benchmark、redis-stat,它们的作用如下: redis-server:Redis服务器的daemon启动程序 redis-cli:Redis命令行操作工具。当然,你也可以用telnet根据其纯文本协议来操作 redis-benchmark:Redis性能测试工具,测试Redis在你的系统及你的配置下的读写性能 redis-stat:Redis状态检测工具,可以检测Redis当前状态参数及延迟状况 在后面会有这几个命令的说明,当然是从网上抄的。。。 五、修改配置文件 /etc/sysctl.conf 添加 vm.overcommit_memory=1 刷新配置使之生效 sysctl vm.overcommit_memory=1 补充介绍: **如果内存情况比较紧张的话,需要设定内核参数: echo 1 > /proc/sys/vm/overcommit_memory 内核参数说明如下: overcommit_memory文件指定了内核针对内存分配的策略,其值可以是0、1、2。 0, 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。 1, 表示内核允许分配所有的物理内存,而不管当前的内存状态如何。 2, 表示内核允许分配超过所有物理内存和交换空间总和的内存 **编辑redis.conf配置文件(/etc/redis.conf),按需求做出适当调整,比如: daemonize yes #转为守护进程,否则启动时会每隔5秒输出一行监控信息 save 60 1000 #减小改变次数,其实这个可以根据情况进行指定 maxmemory 256000000 #分配256M内存 在我们成功安装Redis后,我们直接执行redis-server即可运行Redis,此时它是按照默认配置来运行的(默认配置甚至不是后台运 行)。我们希望Redis按我们的要求运行,则我们需要修改配置文件,Redis的配置文件就是我们上面第二个cp操作的redis.conf文件,目前 它被我们拷贝到了/usr/local/redis/etc/目录下。修改它就可以配置我们的server了。如何修改?下面是redis.conf的主 要配置参数的意义: daemonize:是否以后台daemon方式运行 pidfile:pid文件位置 port:监听的端口号 timeout:请求超时时间 loglevel:log信息级别 logfile:log文件位置 databases:开启数据库的数量 save * :保存快照的频率,第一个表示多长时间,第三个*表示执行多少次写操作。在一定时间内执行一定数量的写操作时,自动保存快照。可设置多个条件。 rdbcompression:是否使用压缩 dbfilename:数据快照文件名(只是文件名,不包括目录) dir:数据快照的保存目录(这个是目录) appendonly:是否开启appendonlylog,开启的话每次写操作会记一条log,这会提高数据抗风险能力,但影响效率。 appendfsync:appendonlylog如何同步到磁盘(三个选项,分别是每次写都强制调用fsync、每秒启用一次fsync、不调用fsync等待系统自己同步) 下面是一个略做修改后的配置文件内容: daemonize yes pidfile /usr/local/redis/var/redis.pid port 6379 timeout 300 loglevel debug logfile /usr/local/redis/var/redis.log databases 16 save 900 1 save 300 10 save 60 10000 rdbcompression yes dbfilename dump.rdb dir /usr/local/redis/var/ appendonly no appendfsync always glueoutputbuf yes shareobjects no shareobjectspoolsize 1024 将上面内容写为redis.conf并保存到/usr/local/redis/etc/目录下 然后在命令行执行: 1 /usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf 即可在后台启动redis服务,这时你通过 1 telnet 127.0.0.1 6379 即可连接到你的redis服务。 六、启动服务并验证 启动服务器 ./redis-server 或 $redis-server /etc/redis.conf 查看是否成功启动 $ ps -ef | grep redis 或 ./redis-cli ping PONG 七、启动命令行客户端赋值取值 redis-cli set mykey somevalue ./redis-cli get mykey 八、关闭服务 $ redis-cli shutdown #关闭指定端口的redis-server $redis-cli -p 6380 shutdown 九、客户端也可以使用telnet形式连接。 [root@dbcache conf]# telnet 127.0.0.1 6379 Trying 127.0.0.1... Connected to dbcache (127.0.0.1). Escape character is '^]'. set foo 3 bar +OK get foo $3 bar ^] telnet> quit Connection closed. 答案来源于网络

养狐狸的猫 2019-12-02 02:17:01 0 浏览量 回答数 0

回答

redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类keyvalue存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Python,Ruby,Erlang,PHP客户端,使用很方便。问题是这个项目还很新,可能还不足够稳定, redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类keyvalue存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Python,Ruby,Erlang,PHP客户端,使用很方便。问题是这个项目还很新,可能还不足够稳定,而且没有在实际的一些大型系统应用的实例。此外,缺乏mc中批量get也是比较大的问题,始终批量获取跟多次获取的网络开销是不一样的。 性能测试结果: SET操作每秒钟 110000 次,GET操作每秒钟 81000 次,服务器配置如下: Linux 2.6, Xeon X3320 2.5Ghz. stackoverflow 网站使用 Redis 做为缓存服务器。 安装过程: Redis是一种高级key-value数据库。它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富。有字符串,链表,集 合和有序集合。支持在服务器端计算集合的并,交和补集(difference)等,还支持多种排序功能。所以Redis也可以被看成是一个数据结构服务 器。 Redis的所有数据都是保存在内存中,然后不定期的通过异步方式保存到磁盘上(这称为“半持久化模式”);也可以把每一次数据变化都写入到一个append only file(aof)里面(这称为“全持久化模式”)。 一、下载最新版 wget http://redis.googlecode.com/files/redis-2.0.0-rc4.tar.gz 二、解压缩 tar redis-2.0.0-rc4.tar.gz 三、安装C/C++的编译组件(非必须) apt-get install build-essential 四、编译 cd redis-2.0.0-rc4 make make命令执行完成后,会在当前目录下生成本个可执行文件,分别是redis-server、redis-cli、redis-benchmark、redis-stat,它们的作用如下: redis-server:Redis服务器的daemon启动程序 redis-cli:Redis命令行操作工具。当然,你也可以用telnet根据其纯文本协议来操作 redis-benchmark:Redis性能测试工具,测试Redis在你的系统及你的配置下的读写性能 redis-stat:Redis状态检测工具,可以检测Redis当前状态参数及延迟状况 在后面会有这几个命令的说明,当然是从网上抄的。。。 五、修改配置文件 /etc/sysctl.conf 添加 vm.overcommit_memory=1 刷新配置使之生效 sysctl vm.overcommit_memory=1 补充介绍: **如果内存情况比较紧张的话,需要设定内核参数: echo 1 > /proc/sys/vm/overcommit_memory 内核参数说明如下: overcommit_memory文件指定了内核针对内存分配的策略,其值可以是0、1、2。 0, 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。 1, 表示内核允许分配所有的物理内存,而不管当前的内存状态如何。 2, 表示内核允许分配超过所有物理内存和交换空间总和的内存 **编辑redis.conf配置文件(/etc/redis.conf),按需求做出适当调整,比如: daemonize yes #转为守护进程,否则启动时会每隔5秒输出一行监控信息 save 60 1000 #减小改变次数,其实这个可以根据情况进行指定 maxmemory 256000000 #分配256M内存 在我们成功安装Redis后,我们直接执行redis-server即可运行Redis,此时它是按照默认配置来运行的(默认配置甚至不是后台运 行)。我们希望Redis按我们的要求运行,则我们需要修改配置文件,Redis的配置文件就是我们上面第二个cp操作的redis.conf文件,目前 它被我们拷贝到了/usr/local/redis/etc/目录下。修改它就可以配置我们的server了。如何修改?下面是redis.conf的主 要配置参数的意义: daemonize:是否以后台daemon方式运行 pidfile:pid文件位置 port:监听的端口号 timeout:请求超时时间 loglevel:log信息级别 logfile:log文件位置 databases:开启数据库的数量 save * *:保存快照的频率,第一个*表示多长时间,第三个*表示执行多少次写操作。在一定时间内执行一定数量的写操作时,自动保存快照。可设置多个条件。 rdbcompression:是否使用压缩 dbfilename:数据快照文件名(只是文件名,不包括目录) dir:数据快照的保存目录(这个是目录) appendonly:是否开启appendonlylog,开启的话每次写操作会记一条log,这会提高数据抗风险能力,但影响效率。 appendfsync:appendonlylog如何同步到磁盘(三个选项,分别是每次写都强制调用fsync、每秒启用一次fsync、不调用fsync等待系统自己同步) 下面是一个略做修改后的配置文件内容: daemonize yes pidfile /usr/local/redis/var/redis.pid port 6379 timeout 300 loglevel debug logfile /usr/local/redis/var/redis.log databases 16 save 900 1 save 300 10 save 60 10000 rdbcompression yes dbfilename dump.rdb dir /usr/local/redis/var/ appendonly no appendfsync always glueoutputbuf yes shareobjects no shareobjectspoolsize 1024 将上面内容写为redis.conf并保存到/usr/local/redis/etc/目录下 然后在命令行执行: 1 /usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf 即可在后台启动redis服务,这时你通过 1 telnet 127.0.0.1 6379 即可连接到你的redis服务。 六、启动服务并验证 启动服务器 ./redis-server 或 $redis-server /etc/redis.conf 查看是否成功启动 $ ps -ef | grep redis 或 ./redis-cli ping PONG 七、启动命令行客户端赋值取值 redis-cli set mykey somevalue ./redis-cli get mykey 八、关闭服务 $ redis-cli shutdown #关闭指定端口的redis-server $redis-cli -p 6380 shutdown 九、客户端也可以使用telnet形式连接。 [root@dbcache conf]# telnet 127.0.0.1 6379 Trying 127.0.0.1... Connected to dbcache (127.0.0.1). Escape character is '^]'. set foo 3 bar +OK get foo $3 bar ^] telnet> quit Connection closed. “答案来源于网络,供您参考” 希望以上信息可以帮到您!

牧明 2019-12-02 02:15:43 0 浏览量 回答数 0

回答

1.1 认识视图界面 和大多编辑器一样,该有的基本都有。 1.2 文件夹和文件的打开 文件——>打开文件夹/打开文件 1.3 新建文件/文件夹 新建文件: a. 文件——>新建文件; b. 按Ctrl+n; c. 点文件夹名后面的+号图标。 新建文件夹: 点文件夹名后面的+号图标。 1.4 拆分编辑器(分列) 快加键:Ctrl+\ 点击拆分编辑器图标(右上角)进行拆分编辑器。拆分完毕之后,可以通过鼠标点击拖动文件到相应的列。多列同时浏览免去多文件来回切换。 1.5 集成终端 终端对开发者来说不可或缺,Visual Studio code 自然也自带终端视窗。 可按快捷键Ctrl+`快速调出终端,也可以 查看——>集成终端 调出。 需要注意的是:如果当前的文件夹的路径名称包含中文,会出现终端打开失败(待验证)。 1.6 安装/卸载扩展(插件) a. 进入扩展视图界面安装/卸载 a1.快捷键:Ctrl+shift+x; a2.查看——>扩展; a3.点左侧边框的扩展图标按钮进入。 在顶部搜索框输入你需要的扩展插件,找到之后在扩展插件后面的选项中点击【安装】即可,需要卸载扩展只需要点【卸载】即可。 扩展下载安装完毕之后需要点击【启用】才生效,有些扩展需要重启编辑器才生效。 b. 如何选择扩展(插件)呢? 其实也不难,扩展的名称一般都暴露了它的功能,基本如下: 1.带snippets 一般是代码提示类扩展; 2.带viewer 一般是代码运行预览类扩展; 3.带support 一般是代码语言支持; 4.带document 一般是参考文档类扩展; 5.带Formatt 一般是代码格式化整理扩展; 当然有的snippets 也自带support功能,并不是以上面的关键词作为唯一标准。 1.7 文件图标主题设置 之前写的有一篇经验,链接附上。 0Visual Studio Code 怎么设置文件图标主题? END 2.VS code用户设置 2.1 用户设置入口 VS code支持用户自定义设置编辑器,包括快加键修改、代码高亮、以及扩展插件配置等,点击文件——>首选项——>用户设置。 编辑器会拆分为两列,一个文件是【默认设置】,一个是【settings.json】,用户设置是空的【settings.json】这个文件(之前没有设置的话),需要自定义的设置项就在settings.json文件里写入json代码即可。 2.2 自定义的设置方法为: 1、在【默认设置】里找到相关的设置json代码段,复制该设置完整的json块,例如:【"editor.fontSize": 14,】。 2、到【settings.json】粘贴。不过记得加上外层(前后)“{}”符号,不然不是完整的json,会出错或者设置无效。 例如: { "editor.fontSize": 20} 完后按Ctrl+s保存关掉窗口,编辑器的文字的大小就变成20了。 需要注意的是,【settings.json】的代码必须符合json格式,且名称(如上面的editor.fontSize)和值对(如上面的20)是【默认设置】里有的或者是扩展中支持的,不然不会有任何作用。 END 3.插件推荐及使用配置 VS code的扩展还是比较丰富的,具体选择方法在前面的步骤1.6已经教大家了,下面介绍几个对基本web前端编辑比较实用的扩展插件(我个人认为)。 3.1 HTNL Snippets 为HTML文档提供代码提示功能,包含HTML5。 3.2 easyless为less文档提供提示,错误警告,以及把less文档编译为css文件。可自定义设置。开发者给出的配置例子: "less.compile": {"compress": true,"sourceMap": true,"out":false} 可以粘贴到用户设置的【默认设置】里,也可以粘贴到用户设置settings.json里。后面的懂json的同学自动忽略:如果settings.json是空的,应该写成: {"less.compile": {"compress": true,"sourceMap": true,"out":false}} 如果之前已有写入json代码,你应该在前面的名称/值对块后面加上“,”(新手容易多加或者少加","符号,个人觉得是这样的)。 ****提示:**** 在写的时候,代码内最好不要加注释。"sourceMap": true, 这个地方最好设置成false ,因为当你实际使用的时候浏览器找不到sourceMap 可能会报错或者浏览器一直去找,还没遇到过(我碰到jQuery.js因为这个报错的),入门的同学还是设置成false 比较好。 3.3 VS color Picker 为css文档和HTML文档提供颜色选择,当输入“#”后会出现颜色选择器浮窗,点击相应颜色之后会插入文档中,默认用16进制表示。若想用其他格式的颜色,如RGB等则推荐扩展:Color Picker (Color Picker缺点是需要配置,安装nodejs,并且添加node到全局环境变量中。而且在插入时需要使用命令调出提色板,有点麻烦) 3.4 live HTML Previewer 为html文档提供预览功能,需要用命令或者快捷键调出,会在编辑器中新增一列,用于运行html文件。 a. 按F1在命令框中输入:Show side preview 新增一列显示html,能边写边看到效果,实时预览。 b. 可以在html文档中右键选择:Open in browser 在系统默认浏览器中打开,该模式下不能提供实时预览,保存时不自动刷新浏览器。 3.5 SVG Viewer 为SVG 文档在编辑器中提供预览。 a. 按F1在命令框中输入:SVG b. 选择SVG Viewer,新增一列显示SVG运行结果。 END 4.VS code 用户代码片段 4.1 用户代码片段 设置入口及示例 用户代码片段 是用来提示代码提示及快捷插入的,那么怎么做呢? 1.文件——>首选项——>用户代码片段 2.选择代码语言 3.按固定格式写json代码 示例格式: "Print to console": {"prefix": "log", "body": ["console.log('$1');","$2"],"description": "Log output to console"} 4.2 片段json示例写法详解 可变区域(这里用XXXX表示)如下:A. "Print to XXXX": { //仅作为标识和目的用途,区别于其他代码块(有多个相同值时会报错),不会插入。 B."prefix": "XXXX", //触发提示的关键字符,也就是输入什么时弹出提示窗。例如:当希望输入a的时候就弹出,这里就写a。在提示窗显示。 C. "body": ["XXXX $1 XXXX"], //在编辑器中插入的代码块,例如当在提示窗中选择a的时候就插入【<a>a</a>】那么这里就写:<a>a</a> D. "description": "XXXX" // 这里是相关描述,比如说明插入的代码块内容、用途、代码结构、参数等,仅在提示窗显示不会插入} E. 上面示例中的$1和$2是初始定位光标位置,用于插入后需要修改的值、参数等。还是上面的例子: "body":["<a>$1</a>"] 那么在插入<a></a>之后,光标的位置将处于<a>和</a>的中间。再如: "body":["<a>$1</a>", "<span>$2GBK</span>"] 那么在插入 <a></a> <span>GBK</span> 之后,光标首先在a标签内,输入完内容之后,光标跳到<span>和GBK中间。输入或者移动光标之后光标恢复正常 4.3 怎么使插入的代码块符合格式化标准? 代码格式化主要就是缩进和换行了。 1.要缩进的地方按下TAB键即可,例如:[" <a>$1</a>"] 2.怎么在"body":[]中插入带双引号的内容?因为注释带有特殊符号尤其是带有双引号("")的内容会导致json报错,解决方法是用反斜杠“\”对特殊符号进行转义。 例如: 那么"body":[]那里应该这样写: 这里在"description": "XXXX"那里同样适用。 总的来说,碰到json报错的字符或者符号就用反斜杠“\”进行转义。当然你要考虑插入之后会不会影响程序文档报错或者出现异常,也就是要先确定插入的代码块是正确的完整的,这是自定义代码块存在的意义 4.4 下面是我写的一段完整的示例(XXXX都匿了):自定义的json{ "Print to authorInfo": { "prefix": "au", "body": [ "-----By Ray-----", "mail:XXXXXXX", "description:$1", " Step 1:", " Step 2:", "<a href=\"XXXX/\">凯玩网</a>"], "description": "author info" 来源于网络,供您参考

保持可爱mmm 2019-12-02 02:20:23 0 浏览量 回答数 0

问题

应用 AXIS 开始 Web 服务之旅:报错

kun坤 2020-06-08 11:01:46 3 浏览量 回答数 1

问题

【精品问答】Java必备核心知识1000+(附源码)

问问小秘 2019-12-01 22:00:28 870 浏览量 回答数 1

问题

企业运营对DevOps的「傲慢与偏见」

忆远0711 2019-12-01 21:32:29 9823 浏览量 回答数 0

问题

Mantis 安装配置手册:报错

kun坤 2020-06-06 14:10:01 0 浏览量 回答数 1

回答

Java Java核心技术·卷 I(原书第10版)| Core Java Volume 讲的很全面,书中的代码示例都很好,很适合Java入门。 但是作者不太厚道的是把现在没人用的GUI编程放在了第一卷,基本上10~13章是可以不用读的。 Java性能权威指南|Java Performance: The Definitive Guide 市面上介绍Java的书有很多,但专注于Java性能的并不多,能游刃有余地展示Java性能优化难点的更是凤毛麟角,本书即是其中之一。 通过使用JVM和Java平台,以及Java语言和应用程序接口,本书详尽讲解了Java性能调优的相关知识,帮助读者深入理解Java平台性能的各个方面,最终使程序如虎添翼。 实战Java高并发程序设计|葛一鸣 由部分段落的行文来看,搬了官方文档。 也有一些第一人称的叙述和思考,也能看出作者也是花了一点心思的。胜在比较基础,涉及到的知识点也还很全面(讲到了流水线计算和并发模型这些边边角角的),但是由于是编著,全书整体上不够统一和深入,适合作为学习高并发的第一本工具书。 Java 8实战 对Java8的新特性讲解的十分到位,尤其是lamdba表达式和流的操作。 再者对于Java8并发处理很有独到见解。对于并行数据处理和组合式异步编程还需要更深的思考才能更加掌握。 推荐给再用java8但没有去真正了解的人看,有很多你不知道的细节、原理和类库设计者的用心良苦在里面、内容没有很难,抽出几个小时就能看完,花费的时间和收获相比,性价比很高。 Java并发编程实战 先不谈本书的内容如何,光书名就足够吸引不少目光。“并发”这个词在Java世界里往往和“高级、核心”等字眼相联系起来,就冲着这两个字,都将勾起软件工程师们埋藏在心底那种对技术的探索欲和对高级API的驾驭感。 程序员嘛,多少都有点职业病。其实Java对“并发”优化从未停止过,从5.0到7.0,几乎每个版本的新特性里,都会针对前一版本在“并发”上有所改进。这种改进包括提供更丰富的API接口、JVM底层性能优化等诸多方面。 Thinking in Java 很美味的一本书,不仅有icecreamm,sundae,sandwich,还有burrito!真是越看越饿啊~ Effective Java中文版(第3版)|Effective Java Third Edition Java 高阶书籍,小白劝退。介绍了关于Java 编程的90个经验技巧。 作者功力非常强悍,导致这本书有时知识面迁移很广。总之,非常适合有一定Java开发经验的人阅读提升。 深入理解Java虚拟机(第3版)| 周志明 浅显易懂。最重要的是开启一扇理解虚拟机的大门。 内存管理机制与Java内存模型、高效并发这三章是特别实用的。 Java虚拟机规范(Java SE 8版)|爱飞翔、周志明 整本书就觉得第二章的方法字节码执行流程,第四章的前8节和第五章能看懂一些。其他的过于细致和琐碎了。 把Java字节码讲的很清楚了,本质上Java虚拟机就是通过字节码来构建的一套体系罢了。所以字节码说的非常细致深入。 数据&大数据 数据结构与算法分析|Data Structures and Algorithm Analysis in Java 数据结构是计算机的核心,这部书以java语言为基础,详细的介绍了基本数据结构、图、以及相关的排序、最短路径、最小生成树等问题。 但是有一些高级的数据结构并没有介绍,可以通过《数据结构与算法分析——C语言描述》来增加对这方面的了解。 MySQL必知必会 《MySQL必知必会》MySQL是世界上最受欢迎的数据库管理系统之一。 书中从介绍简单的数据检索开始,逐步深入一些复杂的内容,包括联结的使用、子查询、正则表达式和基于全文本的搜索、存储过程、游标、触发器、表约束,等等。通过重点突出的章节,条理清晰、系统而扼要地讲述了读者应该掌握的知识,使他们不经意间立刻功力大增。 数据库系统概念|Datebase System Concepts(Fifth Edition) 从大学读到现在,每次拿起都有新的收获。而且这本书还是对各个数据相关领域的概览,不仅仅是数据库本身。 高性能MySQL 对于想要了解MySQL性能提升的人来说,这是一本不可多得的书。 书中没有各种提升性能的秘籍,而是深入问题的核心,详细的解释了每种提升性能的原理,从而可以使你四两拨千斤。授之于鱼不如授之于渔,这本书做到了。 高可用MySQL 很实用的书籍,只可惜公司现有的业务和数据量还没有达到需要实践书中知识的地步。 利用Python进行数据分析|唐学韬 内容还是跟不上库的发展速度,建议结合里面讲的库的文档来看。 内容安排上我觉得还不错,作者是pandas的作者,所以对pandas的讲解和设计思路都讲得很清楚。除此以外,作者也是干过金融数据分析的,所以后面专门讲了时间序列和金融数据的分析。 HBase 看完影印版第一遍,开始以为会是大量讲API,实际上除了没有将HBase源代码,该讲的都讲了,CH8,9章留到最后看的,确实有点顿悟的感觉,接下来需要系统的看一遍Client API,然后深入代码,Come ON! Programming Hive Hive工具书,Hive高级特性。 Hadoop in Practice| Alex Holmes 感觉比action那本要强 像是cookbook类型的 整个过完以后hadoop生态圈的各种都接触到了 这本书适合当参考手册用。 Hadoop技术内幕|董西成 其实国人能写这样的书,感觉还是不错的,不过感觉很多东西不太深入,感觉在深入之前,和先有整体,带着整体做深入会更好一点, jobclient,jobtracer,tasktracer之间的关系最好能系统化 Learning Spark 很不错,core的原理部分和api用途解释得很清楚,以前看文档和代码理解不了的地方豁然开朗。 不足的地方是后几章比较弱,mllib方面没有深入讲实现原理。graphx也没有涉及 ODPS权威指南 基本上还算一本不错的入门,虽然细节方面谈的不多,底层也不够深入,但毕竟是少有的ODPS书籍,且覆盖面很全,例子也还行。 数据之巅|徐子沛 从一个新的视角(数据)切入,写美国历史,统计学的发展贯穿其中,草蛇灰线,伏脉千里,读起来波澜壮阔。 消息队列&Redis RabbitMQ实战 很多年前的书了,书中的例子现在已经不适用了,推荐官方教程。 一些基础还是适用,网上也没有太多讲rab的书籍,将就看下也行,我没用过所以…. Apache Kafka源码剖析|徐郡明 虽然还没看,但知道应该不差。我是看了作者的mybatis源码分析,再来看这本的,相信作者。 作者怎么有这么多时间,把框架研究的这么透彻,佩服,佩服。 深入理解Kafka:核心设计与实践原理|朱忠华 通俗易懂,图文并茂,用了很多图和示例讲解kafka的架构,从宏观入手,再讲到细节,比较好,值得推荐。 深入理解Kafka是市面上讲解Kafka核心原理最透彻的,全书都是挑了kafka最核心的细节在讲比如分区副本选举、分区从分配、kafka数据存储结构、时间轮、我认为是目前kafka相关书籍里最好的一本。 Kafka 认真刷了 kafka internal 那章,看了个talk,算是入了个门。 系统设计真是门艺术。 RocketMQ实战与原理解析|杨开元 对RocketMQ的脉络做了一个大概的说明吧,深入细节的东西还是需要自己看代码 Redis设计与实现|黄健宏 部分内容写得比较啰嗦,当然往好了说是对新手友好,不厌其烦地分析细节,但也让整本书变厚了,个人以为精炼语言可以减少20%的内容。 对于有心一窥redis实现原理的读者来说,本书展露了足够丰富的内容和细节,却不至于让冗长的实现代码吓跑读者——伪代码的意义在此。下一步是真正读源码了。 Redis 深度历险:核心原理与应用实践|钱文品 真心不错,数据结构原理+实际应用+单线程模型+集群(sentinel, codis, redis cluster), 分布式锁等等讲的都十分透彻。 一本书的作用不就是系统性梳理,为读者打开一扇窗,读者想了解更多,可以自己通过这扇窗去Google。这本书的一个瑕疵是最后一章吧,写的仓促了。不过瑕不掩瑜。 技术综合 TCP/IP详解 卷1:协议 读专业性书籍是一件很枯燥的事,我的建议就是把它作为一本手册,先浏览一遍,遇到问题再去详细查,高效。 Netty in Action 涉及到很多专业名词新概念看英文原版顺畅得多,第十五章 Choosing the right thread model 真是写得太好了。另外结合Ron Hitchens 写的《JAVA NIO》一起看对理解JAVA NIO和Netty还是很有帮助的 ZooKeeper 值得使用zookeeper的人员阅读, 对于zookeeper的内部机制及api进行了很详细的讲解, 后半部分深入地讲解了zookeeper中ensemble互相协作的流程, 及group等高级配置, 对zookeeper的高级应用及其它类似系统的设计都很有借鉴意义. 从Paxos到Zookeeper|倪超 分布式入门鼻祖,开始部分深入阐述cap和base理论,所有的分布式框架都是围绕这个理论的做平衡和取舍,中间 zk的原理、特性、实战也讲的非常清晰,同时讲cap理论在zk中是如何体现,更加深你对cap的理解. 深入理解Nginx(第2版)|陶辉 云里雾里的快速读了一遍,主要是读不懂,读完后的感受是设计的真好。 原本是抱着了解原理进而优化性能的想法来读的,却发现书中的内容都是讲源码,作者对源码的注释超级详细,非常适合开发者,但不适合使用者,给个五星好评是因为不想因为我这种菜鸡而埋没了高质量内容。 另外别人的代码写的真好看,即便是过程式语言程序也吊打我写的面向对象语言程序。 作者是zookeeper的活跃贡献者,而且是很资深的研究员,内容比较严谨而且较好的把握住了zk的精髓。书很薄,但是没有废话,选题是经过深思熟虑的。 深入剖析Tomcat 本书深入剖析Tomcat 4和Tomcat 5中的每个组件,并揭示其内部工作原理。通过学习本书,你将可以自行开发Tomcat组件,或者扩展已有的组件。 Tomcat是目前比较流行的Web服务器之一。作为一个开源和小型的轻量级应用服务器,Tomcat 易于使用,便于部署,但Tomcat本身是一个非常复杂的系统,包含了很多功能模块。这些功能模块构成了Tomcat的核心结构。本书从最基本的HTTP请求开始,直至使用JMX技术管理Tomcat中的应用程序,逐一剖析Tomcat的基本功能模块,并配以示例代码,使读者可以逐步实现自己的Web服务器。 深入理解计算机系统 | 布莱恩特 无论是内容还是纸张印刷,都是满分。计算机学科的集大成之作。引导你如何练内功的,算是高配版本的计算机导论,目的是釜底抽薪引出来操作系统、组成原理这些专业核心的课程。帮助我们按图索骥,点亮一个一个技能树。 架构探险分布式服务框架 | 李业兵 刚看前几章的时候,心里满脑子想得都是这特么贴一整页pom文件代码上来干鸡毛,又是骗稿费的,买亏了买亏了,后来到序列化那章开始,诶?还有那么点意思啊。 到服务注册中心和服务通讯,60块钱的书钱已经赚回来了。 知识是无价的,如果能花几十块钱帮你扫了几个盲区,那就是赚了。 深入分析JavaWeb技术内幕 | 许令波 与这本书相识大概是四年前是在老家的北方图书城里,当时看到目录的感觉是真的惊艳,对当时刚入行的自己来说,这简直就是为我量身定做的扫盲科普集啊。 但是可惜的是,这本书在后来却一直没机会读上。然后经过四年的打怪升级之后,这次的阅读体验依旧很好。 其中,java编译原理、 Servlet工作原理、 Tomcat、spring和iBatis这几章的收获很大。 前端 jQuery 技术内幕| 高云 非常棒的一本书,大大降低了阅读jquery源码的难度(虽然还是非常难)。 Head First HTML与CSS(第2版) 翻了非常久的时间 断断续续 其实从头翻到尾 才发现一点都不难。 可我被自己的懒惰和畏难情绪给拖累了 简单说 我成了自己往前探索的负担。网页基础的语法基本都涵盖了 限于文本形态 知识点都没法像做题一样被反复地运用和复习到。通俗易懂 这不知算是多高的评价? 作为入门真心算不错了 如果更有耐心 在翻完 HTML 后 对 CSS 部分最好是可以迅速过一遍 找案例练习估计更好 纸上得来终觉浅 总是这样。 JavaScript高级程序设计(第3版) JavaScript最基础的书籍,要看认真,慢慢地看,累计接近1000小时吧。而且对象与继承,性能优化,HTML5 api由于没有实践或缺乏代码阅读量导致看的很糊涂,不过以后可以遇到时再翻翻,或者看更专业的书。 深入理解ES6 Zakas的又一部杰作,他的作品最优秀的地方在于只是阐述,很少评价,这在帮助我们夯实基础时十分有意义,我也喜欢这种风格。 我是中英文参照阅读的,译本后半部分有一些文字上的纰漏,但是总体来说忠实原文,水平还是相当不错,希望再版时可以修复这些文字问题。 高性能JavaScript 还是挺不错的。尤其是对初学者。总结了好多程序方面的好习惯。 不过对于老手来说,这些常识已经深入骨髓了。 深入浅出Node.js|朴灵 本书是我看到现在对Node.JS技术原理和应用实践阐述的最深入,也最全面的一本书。鉴于作者也是淘宝的一位工程师,在技术总是国外好的大环境下,没有理由不给本书五颗星。 作者秉着授人于鱼不如授人于渔的精神,细致入微的从V8虚拟机,内存管理,字符串与Buffer的应用,异步编程的思路和原理这些基础的角度来解释Node.JS是如何工作的,比起市面上众多教你如何安装node,用几个包编写一些示例来比,本书绝对让人受益匪浅。 认真看完本书,几乎可以让你从一个Node的外行进阶到专家的水平。赞! 总结 其实我觉得在我们现在这个浮躁的社会,大家闲暇时间都是刷抖音,逛淘宝,微博……他们都在一点点吞噬你的碎片时间,如果你尝试着去用碎片的时间看看书,我想时间久了你自然能体会这样的好处。 美团技术团队甚至会奖励读完一些书本的人,很多公司都有自己的小图书馆,我觉得挺好的。 文章来自:敖丙

剑曼红尘 2020-03-20 14:52:22 0 浏览量 回答数 0

回答

该工具可以实现以下两个功能 将 ES6 转换为 ES5支持在 JS 文件中 import CSS 文件 实现 因为涉及到 ES6 转 ES5,所以我们首先需要安装一些 Babel 相关的工具 yarn add babylon babel-traverse babel-core babel-preset-env 接下来我们将这些工具引入文件中 const fs = require('fs') const path = require('path') const babylon = require('babylon') const traverse = require('babel-traverse').default const { transformFromAst } = require('babel-core') 首先,我们先来实现如何使用 Babel 转换代码 function readCode(filePath) { // 读取文件内容 const content = fs.readFileSync(filePath, 'utf-8') // 生成 AST const ast = babylon.parse(content, { sourceType: 'module' }) // 寻找当前文件的依赖关系 const dependencies = [] traverse(ast, { ImportDeclaration: ({ node }) => { dependencies.push(node.source.value) } }) // 通过 AST 将代码转为 ES5 const { code } = transformFromAst(ast, null, { presets: ['env'] }) return { filePath, dependencies, code } } 首先我们传入一个文件路径参数,然后通过 fs 将文件中的内容读取出来接下来我们通过 babylon 解析代码获取 AST,目的是为了分析代码中是否还引入了别的文件通过 dependencies 来存储文件中的依赖,然后再将 AST 转换为 ES5 代码最后函数返回了一个对象,对象中包含了当前文件路径、当前文件依赖和当前文件转换后的代码 接下来我们需要实现一个函数,这个函数的功能有以下几点 调用 readCode 函数,传入入口文件分析入口文件的依赖识别 JS 和 CSS 文件 function getDependencies(entry) { // 读取入口文件 const entryObject = readCode(entry) const dependencies = [entryObject] // 遍历所有文件依赖关系 for (const asset of dependencies) { // 获得文件目录 const dirname = path.dirname(asset.filePath) // 遍历当前文件依赖关系 asset.dependencies.forEach(relativePath => { // 获得绝对路径 const absolutePath = path.join(dirname, relativePath) // CSS 文件逻辑就是将代码插入到 `style` 标签中 if (/\.css$/.test(absolutePath)) { const content = fs.readFileSync(absolutePath, 'utf-8') const code = ` const style = document.createElement('style') style.innerText = ${JSON.stringify(content).replace(/\\r\\n/g, '')} document.head.appendChild(style) ` dependencies.push({ filePath: absolutePath, relativePath, dependencies: [], code }) } else { // JS 代码需要继续查找是否有依赖关系 const child = readCode(absolutePath) child.relativePath = relativePath dependencies.push(child) } }) } return dependencies } 首先我们读取入口文件,然后创建一个数组,该数组的目的是存储代码中涉及到的所有文件接下来我们遍历这个数组,一开始这个数组中只有入口文件,在遍历的过程中,如果入口文件有依赖其他的文件,那么就会被 push 到这个数组中在遍历的过程中,我们先获得该文件对应的目录,然后遍历当前文件的依赖关系在遍历当前文件依赖关系的过程中,首先生成依赖文件的绝对路径,然后判断当前文件是 CSS 文件还是 JS 文件 如果是 CSS 文件的话,我们就不能用 Babel 去编译了,只需要读取 CSS 文件中的代码,然后创建一个 style 标签,将代码插入进标签并且放入 head 中即可如果是 JS 文件的话,我们还需要分析 JS 文件是否还有别的依赖关系最后将读取文件后的对象 push 进数组中 现在我们已经获取到了所有的依赖文件,接下来就是实现打包的功能了 function bundle(dependencies, entry) { let modules = '' // 构建函数参数,生成的结构为 // { './entry.js': function(module, exports, require) { 代码 } } dependencies.forEach(dep => { const filePath = dep.relativePath || entry modules += `'${filePath}': ( function (module, exports, require) { ${dep.code} } ),` }) // 构建 require 函数,目的是为了获取模块暴露出来的内容 const result = ` (function(modules) { function require(id) { const module = { exports : {} } modules[id](module, module.exports, require) return module.exports } require('${entry}') })({${modules}}) ` // 当生成的内容写入到文件中 fs.writeFileSync('./bundle.js', result) } 这段代码需要结合着 Babel 转换后的代码来看,这样大家就能理解为什么需要这样写了 // entry.js var _a = require('./a.js') var _a2 = _interopRequireDefault(_a) function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj } } console.log(_a2.default) // a.js Object.defineProperty(exports, '__esModule', { value: true }) var a = 1 exports.default = a Babel 将我们 ES6 的模块化代码转换为了 CommonJS(如果你不熟悉 CommonJS 的话,可以阅读这一章节中关于 模块化的知识点) 的代码,但是浏览器是不支持 CommonJS 的,所以如果这段代码需要在浏览器环境下运行的话,我们需要自己实现 CommonJS 相关的代码,这就是 bundle 函数做的大部分事情。 接下来我们再来逐行解析 bundle 函数 首先遍历所有依赖文件,构建出一个函数参数对象对象的属性就是当前文件的相对路径,属性值是一个函数,函数体是当前文件下的代码,函数接受三个参数 module、exports、 require module 参数对应 CommonJS 中的 moduleexports 参数对应 CommonJS 中的 module.exportrequire 参数对应我们自己创建的 require 函数 接下来就是构造一个使用参数的函数了,函数做的事情很简单,就是内部创建一个 require 函数,然后调用 require(entry),也就是 require('./entry.js'),这样就会从函数参数中找到 ./entry.js 对应的函数并执行,最后将导出的内容通过 module.export 的方式让外部获取到最后再将打包出来的内容写入到单独的文件中 如果你对于上面的实现还有疑惑的话,可以阅读下打包后的部分简化代码 ;(function(modules) { function require(id) { // 构造一个 CommonJS 导出代码 const module = { exports: {} } // 去参数中获取文件对应的函数并执行 modules[id](module, module.exports, require) return module.exports } require('./entry.js') })({ './entry.js': function(module, exports, require) { // 这里继续通过构造的 require 去找到 a.js 文件对应的函数 var _a = require('./a.js') console.log(_a2.default) }, './a.js': function(module, exports, require) { var a = 1 // 将 require 函数中的变量 module 变成了这样的结构 // module.exports = 1 // 这样就能在外部取到导出的内容了 exports.default = a } // 省略 }) 小结 虽然实现这个工具只写了不到 100 行的代码,但是打包工具的核心原理就是这些了 找出入口文件所有的依赖关系然后通过构建 CommonJS 代码来获取 exports 导出的内容

前端问答 2019-12-23 22:02:13 0 浏览量 回答数 0

问题

【Java学习全家桶】1460道Java热门问题,阿里百位技术专家答疑解惑

管理贝贝 2019-12-01 20:07:15 27612 浏览量 回答数 19

回答

PHP面试干货 1、进程和线程 进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。进程和线程的区别在于: 简而言之,一个程序至少有一个进程,一个进程至少有一个线程. 线程的划分尺度小于进程,使得多线程程序的并发性高。 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。 2、apache默认使用进程管理还是线程管理?如何判断并设置最大连接数? 一个进程可以开多个线程 默认是进程管理 默认有一个主进程 Linux: ps -aux | grep httpd | more 一个子进程代表一个用户的连接 Conf/extra/httpd-mpm.conf 多路功能模块 http -l 查询当前apache处于什么模式下 3、单例模式 单例模式需求:只能实例化产生一个对象 如何实现: 私有化构造函数 禁止克隆对象 提供一个访问这个实例的公共的静态方法(通常为getInstance方法),从而返回唯一对象 需要一个保存类的静态属性 class demo { private static $MyObject; //保存对象的静态属性 private function __construct(){ //私有化构造函数 } private function __clone(){ //禁止克隆 } public static function getInstance(){ if(! (self::$MyObject instanceof self)){ self::$MyObject = new self; } return self::$MyObject; } } 4、安装完Apache后,在http.conf中配置加载PHP文件以Apache模块的方式安装PHP,在文件http.conf中首先要用语句LoadModule php5_module "e:/php/php5apache2.dll"动态装载PHP模块,然后再用语句AddType application/x-httpd-php .php 使得Apache把所有扩展名为PHP的文件都作为PHP脚本处理 5、debug_backtrace()函数能返回脚本里的任意行中调用的函数的名称。该函数同时还经常被用在调试中,用来判断错误是如何发生的 function one($str1, $str2) { two("Glenn", "Quagmire"); } function two($str1, $str2) { three("Cleveland", "Brown"); } function three($str1, $str2) { print_r(debug_backtrace()); } one("Peter", "Griffin"); Array ( [0] => Array ( [file] => D:\www\test\result.php [line] => 9 [function] => three [args] => Array ( [0] => Cleveland [1] => Brown ) ) [1] => Array ( [file] => D:\www\test\result.php [line] => 5 [function] => two [args] => Array ( [0] => Glenn [1] => Quagmire ) ) [2] => Array ( [file] => D:\www\test\result.php [line] => 16 [function] => one [args] => Array ( [0] => Peter [1] => Griffin ) ) ) 6、输出用户的IP地址,并且判断用户的IP地址是否在192.168.1.100 — 192.168.1.150之间 echo $ip=getenv('REMOTE_ADDR'); $ip=str_replace('.','',$ip); if($ip<1921681150 && $ip>1921681100) { echo 'ip在192.168.1.100—–192.168.1.150之间'; } else { echo 'ip不在192.168.1.100—–192.168.1.150之间'; } 7、请将2维数组按照name的长度进行重新排序,按照顺序将id赋值 $tarray = array( array('id' => 0, 'name' => '123'), array('id' => 0, 'name' => '1234'), array('id' => 0, 'name' => '1235'), array('id' => 0, 'name' => '12356'), array('id' => 0, 'name' => '123abc') ); foreach($tarray as $key=>$val) { $c[]=$val['name']; } function aa($a,$b) { if(strlen($a)==strlen($b)) return 0; return strlen($a)>strlen($b)?-1:1; } usort($c,'aa'); $len=count($c); for($i=0;$i<$len;$i++) { $t[$i]['id']=$i+1; $t[$i]['name']=$c[$i]; } print_r($t); 8、表单数据提交方式POST和GET的区别,URL地址传递的数据最大长度是多少? POST方式提交数据用户不可见,是数据更安全,最大长度不受限制,而GET方式传值在URL地址可以看到,相对不安全,对大长度是2048字节。 9、SESSION和COOKIE的作用和区别,SESSION信息的存储方式,如何进行遍历 SESSION和COOKIE都能够使值在页面之间进行传递,SESSION存储在服务器端,数据更安全,COOKIE保存在客户端,用户使用手段可以进行修改,SESSION依赖于COOKIE进行传递的。Session遍历使用$_SESSION[]取值,cookie遍历使用$_COOKIE[]取值。 10、什么是数据库索引,主键索引,唯一索引的区别,索引的缺点是什么 索引用来快速地寻找那些具有特定值的记录。 主键索引和唯一索引的区别:主键是一种唯一性索引,但它必须指定为“PRIMARY KEY”,每个表只能有一个主键。唯一索引索引列的所有值都只能出现一次,即必须唯一。 索引的缺点: 1、创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。 2、索引需要占用物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,需要的空间就会更大。 3、当对表中的数据进行增加、删除、修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。 11、数据库设计时,常遇到的性能瓶颈有哪些,常有的解决方案 瓶颈主要有: 1、磁盘搜索 优化方法是:将数据分布在多个磁盘上 2、磁盘读/写 优化方法是:从多个磁盘并行读写。 3、CPU周期 优化方法:扩充内存 4、内存带宽 12、include和require区别 include引入文件的时候,如果碰到错误,会给出提示,并继续运行下边的代码。 require引入文件的时候,如果碰到错误,会给出提示,并停止运行下边的代码。 13、文件上传时设计到点 和文件上传有关的php.ini配置选项(File Uploads): file_uploads=On/Off:文件是否允许上传 upload_max_filesize上传文件时,单个文件的最大大小 post_max_size:提交表单时,整个post表单的最大大小 max_file_uploads =20上传文件的个数 内存占用,脚本最大执行时间也间接影响到文件的上传 14、header常见状态 //200 正常状态 header('HTTP/1.1 200 OK'); // 301 永久重定向,记得在后面要加重定向地址 Location:$url header('HTTP/1.1 301 Moved Permanently'); // 重定向,其实就是302 暂时重定向 header('Location: http://www.maiyoule.com/'); // 设置页面304 没有修改 header('HTTP/1.1 304 Not Modified'); // 显示登录框, header('HTTP/1.1 401 Unauthorized'); header('WWW-Authenticate: Basic realm="登录信息"'); echo '显示的信息!'; // 403 禁止访问 header('HTTP/1.1 403 Forbidden'); // 404 错误 header('HTTP/1.1 404 Not Found'); // 500 服务器错误 header('HTTP/1.1 500 Internal Server Error'); // 3秒后重定向指定地址(也就是刷新到新页面与 <meta http-equiv="refresh" content="10;http://www.maiyoule.com/ /> 相同) header('Refresh: 3; url=http://www.maiyoule.com/'); echo '10后跳转到http://www.maiyoule.com'; // 重写 X-Powered-By 值 header('X-Powered-By: PHP/5.3.0'); header('X-Powered-By: Brain/0.6b'); //设置上下文语言 header('Content-language: en'); // 设置页面最后修改时间(多用于防缓存) $time = time() - 60; //建议使用filetime函数来设置页面缓存时间 header('Last-Modified: '.gmdate('D, d M Y H:i:s', $time).' GMT'); // 设置内容长度 header('Content-Length: 39344'); // 设置头文件类型,可以用于流文件或者文件下载 header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="example.zip"'); header('Content-Transfer-Encoding: binary'); readfile('example.zip');//读取文件到客户端 //禁用页面缓存 header('Cache-Control: no-cache, no-store, max-age=0, must-revalidate'); header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); header('Pragma: no-cache'); //设置页面头信息 header('Content-Type: text/html; charset=iso-8859-1'); header('Content-Type: text/html; charset=utf-8'); header('Content-Type: text/plain'); header('Content-Type: image/jpeg'); header('Content-Type: application/zip'); header('Content-Type: application/pdf'); header('Content-Type: audio/mpeg'); header('Content-Type: application/x-shockwave-flash'); //.... 至于Content-Type 的值 可以去查查 w3c 的文档库,那里很丰富 15、ORM和ActiveRecord ORM:object relation mapping,即对象关系映射,简单的说就是对象模型和关系模型的一种映射。为什么要有这么一个映射?很简单,因为现在的开发语言基本都是oop的,但是传统的数据库却是关系型的。为了可以靠贴近面向对象开发,我们想要像操作对象一样操作数据库。还可以隔离底层数据库层,我们不需要关心我们使用的是mysql还是其他的关系型数据库 ActiveRecord也属于ORM层,由Rails最早提出,遵循标准的ORM模型:表映射到记录,记录映射到对象,字段映射到对象属性。配合遵循的命名和配置惯例,能够很大程度的快速实现模型的操作,而且简洁易懂。 ActiveRecord的主要思想是: 1. 每一个数据库表对应创建一个类,类的每一个对象实例对应于数据库中表的一行记录;通常表的每个字段在类中都有相应的Field; 2. ActiveRecord同时负责把自己持久化,在ActiveRecord中封装了对数据库的访问,即CURD;; 3. ActiveRecord是一种领域模型(Domain Model),封装了部分业务逻辑; ActiveRecord比较适用于: 1. 业务逻辑比较简单,当你的类基本上和数据库中的表一一对应时, ActiveRecord是非常方便的,即你的业务逻辑大多数是对单表操作; 2. 当发生跨表的操作时, 往往会配合使用事务脚本(Transaction Script),把跨表事务提升到事务脚本中; 3. ActiveRecord最大优点是简单, 直观。 一个类就包括了数据访问和业务逻辑. 如果配合代码生成器使用就更方便了; 这些优点使ActiveRecord特别适合WEB快速开发。 16、斐波那契方法,也就是1 1 2 3 5 8 ……,这里给出两种方法,大家可以对比下,看看哪种快,以及为什么 function fibonacci($n){ if($n == 0){ return 0; } if($n == 1){ return 1; } return fibonacci($n-1)+fibonacci($n-2); } function fibonacci($n){ for($i=0; $i<$n; $i++){ $r[] = $i<2 ? 1 : $r[$i-1]+$r[$i-2]; } return $r[--$i]; } 17、约瑟夫环,也就是常见的数猴子,n只猴子围成一圈,每只猴子下面标了编号,从1开始数起,数到m那么第m只猴子便退出,依次类推,每数到m,那么那个位置的猴子退出,那么最后剩下的猴子下的编号是啥。 function yuesefu($n,$m) { $r=0; for($i=2; $i<=$n; $i++) { $r=($r+$m)%$i; } return $r+1; } 18、冒泡排序,大致是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换,这样一趟过去后,最大或最小的数字被交换到了最后一位,然后再从头开始进行两两比较交换,直到倒数第二位时结束 function bubbleSort($arr){ for($i=0, $len=count($arr); $i<$len; $i++){ for($j=0; $j<$len; $j++){ if($arr[$i]<$arr[$j]){ $tmp = $arr[$j]; $arr[$j] = $arr[$i]; $arr[$i] = $tmp; } } } return $arr; } 19、快速排序,也就是找出一个元素(理论上可以随便找一个)作为基准,然后对数组进行分区操作,使基准左边元素的值都不大于基准值,基准右边的元素值 都不小于基准值,如此作为基准的元素调整到排序后的正确位置。递归快速排序,将其他n-1个元素也调整到排序后的正确位置。最后每个元素都是在排序后的正 确位置,排序完成。所以快速排序算法的核心算法是分区操作,即如何调整基准的位置以及调整返回基准的最终位置以便分治递归。 function quickSort($arr){ $len = count($arr); if($len <=1){ return $arr; } $key = $arr[0]; $leftArr = $rightArr= array(); for($i=1; $i<$len; $i++){ if($arr[$i] <= $key){ $leftArr[] = $arr[$i]; } else{ $rightArr[] = $arr[$i]; } } $leftArr = quickSort($leftArr); $rightArr = quickSort($rightArr); return array_merge($leftArr, array($key), $rightArr); } 20、(递归的)列出目录下所有文件及目录,这里也有两种方法 function listDir($path){ $res = dir($path); while($file = $res->read()){ if($file == '.' || $file == '..'){ continue; } if(is_dir($path . '/' .$file)){ echo $path . '/' .$file . "\r\n"; listDir($path . '/' .$file); } else{ echo $path . '/' .$file . "\r\n"; } } $res->close(); } function listDir($path){ if(is_dir($path)){ if(FALSE !== ($res = opendir($path))){ while(FALSE !== ($file = readdir($res))){ if($file == '.' || $file == '..'){ continue; } $subPath = $path . '/' . $file; if(is_dir($subPath)){ echo $subPath . "\r\n"; listDir($subPath); } else{ echo $subPath . "\r\n"; } } } } } 21、找出相对的目录,比如/a/b/c/d/e.php相对于/a/b/13/34/c.php是/c/d/ function ralativePath($a, $b){ $a = explode('/', dirname($a)); $b = explode('/', dirname($b)); $c = '/'; foreach ($a as $k=> $v){ if($v != $b[$k]){ $c .= $v . '/'; } } echo $c; } 22、快速找出url中php后缀 function get_ext($url){ $data = parse_url($url); return pathinfo($data['path'], PATHINFO_EXTENSION); } 23、正则题,使用正则抓取网页,以网页meta为utf8为准,若是抓取的网页编码为big5之类的,需要转化为utf8再收录 function preg_meta($meta){ $replacement = "\\1utf8\\6\\7"; $pattern = '#(<meta\s+http-equiv=(\'|"|)Content-Type(\'|"|)\s+content=(\'|"|)text/html; charset=)(\w+)(\'|"|)(>)#i'; return preg_replace($pattern, $replacement, $meta); } echo preg_meta("<meta http-equiv=Content-Type content='text/html; charset=big5'><META http-equiv=\"Content-Type\" content='text/html; charset=big5'>"); 24、不用php的反转函数倒序输出字符串,如abc,反序输出cba function revstring($str){ for($i=strlen($str)-1; $i>=0; $i--){ echo $str{$i}; } } revstring('abc'); 25、常见端口 TCP 21端口:FTP 文件传输服务 SSH 22端口:SSH连接linux服务器,通过SSH连接可以远程管理Linux等设备 TCP 23端口:TELNET 终端仿真服务 TCP 25端口:SMTP 简单邮件传输服务 UDP 53端口:DNS 域名解析服务 TCP 80端口:HTTP 超文本传输服务 TCP 110端口:POP3 “邮局协议版本3”使用的端口 TCP 443端口:HTTPS 加密的超文本传输服务 TCP 1521端口:Oracle数据库服务 TCP 1863端口:MSN Messenger的文件传输功能所使用的端口 TCP 3389端口:Microsoft RDP 微软远程桌面使用的端口 TCP 5631端口:Symantec pcAnywhere 远程控制数据传输时使用的端口 UDP 5632端口:Symantec pcAnywhere 主控端扫描被控端时使用的端口 TCP 5000端口:MS SQL Server使用的端口 UDP 8000端口:腾讯QQ 26、linux常用的命令 top linux进程实时监控 ps 在Linux中是查看进程的命令。ps查看正处于Running的进程 mv 为文件或目录改名或将文件由一个目录移入另一个目录中。 find 查找文件 df 可显示所有文件系统对i节点和磁盘块的使用情况。 cat 打印文件类容 chmod 变更文件或目录的权限 chgrp 文件或目录的权限的掌控以拥有者及所诉群组来管理。可以使用chgrp指令取变更文件与目录所属群组 grep 是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来。 wc 为统计指定文件中的字节数、字数、行数,并将统计结果显示输出 27、对于大流量的网站,您采用什么样的方法来解决访问量问题 首先,确认服务器硬件是否足够支持当前的流量 其次,优化数据库访问。 第三,禁止外部的盗链。 第四,控制大文件的下载。 第五,使用不同主机分流主要流量 第六,使用流量分析统计软件 28、$_SERVER常用的字段 $_SERVER['PHP_SELF'] #当前正在执行脚本的文件名 $_SERVER['SERVER_NAME'] #当前运行脚本所在服务器主机的名称 $_SERVER['REQUEST_METHOD'] #访问页面时的请求方法。例如:“GET”、“HEAD”,“POST”,“PUT” $_SERVER['QUERY_STRING'] #查询(query)的字符串 $_SERVER['HTTP_HOST'] #当前请求的 Host: 头部的内容 $_SERVER['HTTP_REFERER'] #链接到当前页面的前一页面的 URL 地址 $_SERVER['REMOTE_ADDR'] #正在浏览当前页面用户的 IP 地址 $_SERVER['REMOTE_HOST'] #正在浏览当前页面用户的主机名 $_SERVER['SCRIPT_FILENAME'] #当前执行脚本的绝对路径名 $_SERVER['SCRIPT_NAME'] #包含当前脚本的路径。这在页面需要指向自己时非常有用 $_SERVER['REQUEST_URI'] #访问此页面所需的 URI。例如,“/index.html” 29、安装php扩展 进入扩展的目录 phpize命令得到configure文件 ./configure --with-php-config=/usr/local/php/bin/php-config make & make install 在php.ini中加入扩展名称.so 重启web服务器(nginx/apache) 30、php-fpm与nginx PHP-FPM也是一个第三方的FastCGI进程管理器,它是作为PHP的一个补丁来开发的,在安装的时候也需要和PHP源码一起编译,也就是说PHP-FPM被编译到PHP内核中,因此在处理性能方面更加优秀;同时它在处理高并发方面也比spawn-fcgi引擎好很多,因此,推荐Nginx+PHP/PHP-FPM这个组合对PHP进行解析。 FastCGI 的主要优点是把动态语言和HTTP Server分离开来,所以Nginx与PHP/PHP-FPM经常被部署在不同的服务器上,以分担前端Nginx服务器的压力,使Nginx专一处理静态请求和转发动态请求,而PHP/PHP-FPM服务器专一解析PHP动态请求 #fastcgi FastCGI是一个可伸缩地、高速地在HTTP server和动态脚本语言间通信的接口。多数流行的HTTP server都支持FastCGI,包括Apache、Nginx和lighttpd等,同时,FastCGI也被许多脚本语言所支持,其中就有PHP。 FastCGI是从CGI发展改进而来的。传统CGI接口方式的主要缺点是性能很差,因为每次HTTP服务器遇到动态程序时都需要重新启动脚本解析器来执行解析,然后结果被返回给HTTP服务器。这在处理高并发访问时,几乎是不可用的。另外传统的CGI接口方式安全性也很差,现在已经很少被使用了。 FastCGI接口方式采用C/S结构,可以将HTTP服务器和脚本解析服务器分开,同时在脚本解析服务器上启动一个或者多个脚本解析守护进程。当HTTP服务器每次遇到动态程序时,可以将其直接交付给FastCGI进程来执行,然后将得到的结果返回给浏览器。这种方式可以让HTTP服务器专一地处理静态请求或者将动态脚本服务器的结果返回给客户端,这在很大程度上提高了整个应用系统的性能。 Nginx+FastCGI运行原理 Nginx不支持对外部程序的直接调用或者解析,所有的外部程序(包括PHP)必须通过FastCGI接口来调用。FastCGI接口在Linux下是socket,(这个socket可以是文件socket,也可以是ip socket)。为了调用CGI程序,还需要一个FastCGI的wrapper(wrapper可以理解为用于启动另一个程序的程序),这个wrapper绑定在某个固定socket上,如端口或者文件socket。当Nginx将CGI请求发送给这个socket的时候,通过FastCGI接口,wrapper接纳到请求,然后派生出一个新的线程,这个线程调用解释器或者外部程序处理脚本并读取返回数据;接着,wrapper再将返回的数据通过FastCGI接口,沿着固定的socket传递给Nginx;最后,Nginx将返回的数据发送给客户端,这就是Nginx+FastCGI的整个运作过程。 31、ajax全称“Asynchronous Javascript And XML”(异步JavaScript和XML)

小川游鱼 2019-12-02 01:41:29 0 浏览量 回答数 0

回答

PHP面试干货 1、进程和线程 进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。进程和线程的区别在于: 简而言之,一个程序至少有一个进程,一个进程至少有一个线程. 线程的划分尺度小于进程,使得多线程程序的并发性高。 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。 2、apache默认使用进程管理还是线程管理?如何判断并设置最大连接数? 一个进程可以开多个线程 默认是进程管理 默认有一个主进程 Linux: ps -aux | grep httpd | more 一个子进程代表一个用户的连接 Conf/extra/httpd-mpm.conf 多路功能模块 http -l 查询当前apache处于什么模式下 3、单例模式 单例模式需求:只能实例化产生一个对象 如何实现: 私有化构造函数 禁止克隆对象 提供一个访问这个实例的公共的静态方法(通常为getInstance方法),从而返回唯一对象 需要一个保存类的静态属性 class demo { private static $MyObject; //保存对象的静态属性 private function __construct(){ //私有化构造函数 } private function __clone(){ //禁止克隆 } public static function getInstance(){ if(! (self::$MyObject instanceof self)){ self::$MyObject = new self; } return self::$MyObject; } } 4、安装完Apache后,在http.conf中配置加载PHP文件以Apache模块的方式安装PHP,在文件http.conf中首先要用语句LoadModule php5_module "e:/php/php5apache2.dll"动态装载PHP模块,然后再用语句AddType application/x-httpd-php .php 使得Apache把所有扩展名为PHP的文件都作为PHP脚本处理 5、debug_backtrace()函数能返回脚本里的任意行中调用的函数的名称。该函数同时还经常被用在调试中,用来判断错误是如何发生的 function one($str1, $str2) { two("Glenn", "Quagmire"); } function two($str1, $str2) { three("Cleveland", "Brown"); } function three($str1, $str2) { print_r(debug_backtrace()); } one("Peter", "Griffin"); Array ( [0] => Array ( [file] => D:\www\test\result.php [line] => 9 [function] => three [args] => Array ( [0] => Cleveland [1] => Brown ) ) [1] => Array ( [file] => D:\www\test\result.php [line] => 5 [function] => two [args] => Array ( [0] => Glenn [1] => Quagmire ) ) [2] => Array ( [file] => D:\www\test\result.php [line] => 16 [function] => one [args] => Array ( [0] => Peter [1] => Griffin ) ) ) 6、输出用户的IP地址,并且判断用户的IP地址是否在192.168.1.100 — 192.168.1.150之间 echo $ip=getenv('REMOTE_ADDR'); $ip=str_replace('.','',$ip); if($ip<1921681150 && $ip>1921681100) { echo 'ip在192.168.1.100—–192.168.1.150之间'; } else { echo 'ip不在192.168.1.100—–192.168.1.150之间'; } 7、请将2维数组按照name的长度进行重新排序,按照顺序将id赋值 $tarray = array( array('id' => 0, 'name' => '123'), array('id' => 0, 'name' => '1234'), array('id' => 0, 'name' => '1235'), array('id' => 0, 'name' => '12356'), array('id' => 0, 'name' => '123abc') ); foreach($tarray as $key=>$val) { $c[]=$val['name']; } function aa($a,$b) { if(strlen($a)==strlen($b)) return 0; return strlen($a)>strlen($b)?-1:1; } usort($c,'aa'); $len=count($c); for($i=0;$i<$len;$i++) { $t[$i]['id']=$i+1; $t[$i]['name']=$c[$i]; } print_r($t); 8、表单数据提交方式POST和GET的区别,URL地址传递的数据最大长度是多少? POST方式提交数据用户不可见,是数据更安全,最大长度不受限制,而GET方式传值在URL地址可以看到,相对不安全,对大长度是2048字节。 9、SESSION和COOKIE的作用和区别,SESSION信息的存储方式,如何进行遍历 SESSION和COOKIE都能够使值在页面之间进行传递,SESSION存储在服务器端,数据更安全,COOKIE保存在客户端,用户使用手段可以进行修改,SESSION依赖于COOKIE进行传递的。Session遍历使用$_SESSION[]取值,cookie遍历使用$_COOKIE[]取值。 10、什么是数据库索引,主键索引,唯一索引的区别,索引的缺点是什么 索引用来快速地寻找那些具有特定值的记录。 主键索引和唯一索引的区别:主键是一种唯一性索引,但它必须指定为“PRIMARY KEY”,每个表只能有一个主键。唯一索引索引列的所有值都只能出现一次,即必须唯一。 索引的缺点: 1、创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。 2、索引需要占用物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,需要的空间就会更大。 3、当对表中的数据进行增加、删除、修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。 11、数据库设计时,常遇到的性能瓶颈有哪些,常有的解决方案 瓶颈主要有: 1、磁盘搜索 优化方法是:将数据分布在多个磁盘上 2、磁盘读/写 优化方法是:从多个磁盘并行读写。 3、CPU周期 优化方法:扩充内存 4、内存带宽 12、include和require区别 include引入文件的时候,如果碰到错误,会给出提示,并继续运行下边的代码。 require引入文件的时候,如果碰到错误,会给出提示,并停止运行下边的代码。 13、文件上传时设计到点 和文件上传有关的php.ini配置选项(File Uploads): file_uploads=On/Off:文件是否允许上传 upload_max_filesize上传文件时,单个文件的最大大小 post_max_size:提交表单时,整个post表单的最大大小 max_file_uploads =20上传文件的个数 内存占用,脚本最大执行时间也间接影响到文件的上传 14、header常见状态 //200 正常状态 header('HTTP/1.1 200 OK'); // 301 永久重定向,记得在后面要加重定向地址 Location:$url header('HTTP/1.1 301 Moved Permanently'); // 重定向,其实就是302 暂时重定向 header('Location: http://www.maiyoule.com/'); // 设置页面304 没有修改 header('HTTP/1.1 304 Not Modified'); // 显示登录框, header('HTTP/1.1 401 Unauthorized'); header('WWW-Authenticate: Basic realm="登录信息"'); echo '显示的信息!'; // 403 禁止访问 header('HTTP/1.1 403 Forbidden'); // 404 错误 header('HTTP/1.1 404 Not Found'); // 500 服务器错误 header('HTTP/1.1 500 Internal Server Error'); // 3秒后重定向指定地址(也就是刷新到新页面与 <meta http-equiv="refresh" content="10;http://www.maiyoule.com/ /> 相同) header('Refresh: 3; url=http://www.maiyoule.com/'); echo '10后跳转到http://www.maiyoule.com'; // 重写 X-Powered-By 值 header('X-Powered-By: PHP/5.3.0'); header('X-Powered-By: Brain/0.6b'); //设置上下文语言 header('Content-language: en'); // 设置页面最后修改时间(多用于防缓存) $time = time() - 60; //建议使用filetime函数来设置页面缓存时间 header('Last-Modified: '.gmdate('D, d M Y H:i:s', $time).' GMT'); // 设置内容长度 header('Content-Length: 39344'); // 设置头文件类型,可以用于流文件或者文件下载 header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="example.zip"'); header('Content-Transfer-Encoding: binary'); readfile('example.zip');//读取文件到客户端 //禁用页面缓存 header('Cache-Control: no-cache, no-store, max-age=0, must-revalidate'); header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); header('Pragma: no-cache'); //设置页面头信息 header('Content-Type: text/html; charset=iso-8859-1'); header('Content-Type: text/html; charset=utf-8'); header('Content-Type: text/plain'); header('Content-Type: image/jpeg'); header('Content-Type: application/zip'); header('Content-Type: application/pdf'); header('Content-Type: audio/mpeg'); header('Content-Type: application/x-shockwave-flash'); //.... 至于Content-Type 的值 可以去查查 w3c 的文档库,那里很丰富 15、ORM和ActiveRecord ORM:object relation mapping,即对象关系映射,简单的说就是对象模型和关系模型的一种映射。为什么要有这么一个映射?很简单,因为现在的开发语言基本都是oop的,但是传统的数据库却是关系型的。为了可以靠贴近面向对象开发,我们想要像操作对象一样操作数据库。还可以隔离底层数据库层,我们不需要关心我们使用的是mysql还是其他的关系型数据库 ActiveRecord也属于ORM层,由Rails最早提出,遵循标准的ORM模型:表映射到记录,记录映射到对象,字段映射到对象属性。配合遵循的命名和配置惯例,能够很大程度的快速实现模型的操作,而且简洁易懂。 ActiveRecord的主要思想是: 1. 每一个数据库表对应创建一个类,类的每一个对象实例对应于数据库中表的一行记录;通常表的每个字段在类中都有相应的Field; 2. ActiveRecord同时负责把自己持久化,在ActiveRecord中封装了对数据库的访问,即CURD;; 3. ActiveRecord是一种领域模型(Domain Model),封装了部分业务逻辑; ActiveRecord比较适用于: 1. 业务逻辑比较简单,当你的类基本上和数据库中的表一一对应时, ActiveRecord是非常方便的,即你的业务逻辑大多数是对单表操作; 2. 当发生跨表的操作时, 往往会配合使用事务脚本(Transaction Script),把跨表事务提升到事务脚本中; 3. ActiveRecord最大优点是简单, 直观。 一个类就包括了数据访问和业务逻辑. 如果配合代码生成器使用就更方便了; 这些优点使ActiveRecord特别适合WEB快速开发。 16、斐波那契方法,也就是1 1 2 3 5 8 ……,这里给出两种方法,大家可以对比下,看看哪种快,以及为什么 function fibonacci($n){ if($n == 0){ return 0; } if($n == 1){ return 1; } return fibonacci($n-1)+fibonacci($n-2); } function fibonacci($n){ for($i=0; $i<$n; $i++){ $r[] = $i<2 ? 1 : $r[$i-1]+$r[$i-2]; } return $r[--$i]; } 17、约瑟夫环,也就是常见的数猴子,n只猴子围成一圈,每只猴子下面标了编号,从1开始数起,数到m那么第m只猴子便退出,依次类推,每数到m,那么那个位置的猴子退出,那么最后剩下的猴子下的编号是啥。 function yuesefu($n,$m) { $r=0; for($i=2; $i<=$n; $i++) { $r=($r+$m)%$i; } return $r+1; } 18、冒泡排序,大致是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换,这样一趟过去后,最大或最小的数字被交换到了最后一位,然后再从头开始进行两两比较交换,直到倒数第二位时结束 function bubbleSort($arr){ for($i=0, $len=count($arr); $i<$len; $i++){ for($j=0; $j<$len; $j++){ if($arr[$i]<$arr[$j]){ $tmp = $arr[$j]; $arr[$j] = $arr[$i]; $arr[$i] = $tmp; } } } return $arr; } 19、快速排序,也就是找出一个元素(理论上可以随便找一个)作为基准,然后对数组进行分区操作,使基准左边元素的值都不大于基准值,基准右边的元素值 都不小于基准值,如此作为基准的元素调整到排序后的正确位置。递归快速排序,将其他n-1个元素也调整到排序后的正确位置。最后每个元素都是在排序后的正 确位置,排序完成。所以快速排序算法的核心算法是分区操作,即如何调整基准的位置以及调整返回基准的最终位置以便分治递归。 function quickSort($arr){ $len = count($arr); if($len <=1){ return $arr; } $key = $arr[0]; $leftArr = $rightArr= array(); for($i=1; $i<$len; $i++){ if($arr[$i] <= $key){ $leftArr[] = $arr[$i]; } else{ $rightArr[] = $arr[$i]; } } $leftArr = quickSort($leftArr); $rightArr = quickSort($rightArr); return array_merge($leftArr, array($key), $rightArr); } 20、(递归的)列出目录下所有文件及目录,这里也有两种方法 function listDir($path){ $res = dir($path); while($file = $res->read()){ if($file == '.' || $file == '..'){ continue; } if(is_dir($path . '/' .$file)){ echo $path . '/' .$file . "\r\n"; listDir($path . '/' .$file); } else{ echo $path . '/' .$file . "\r\n"; } } $res->close(); } function listDir($path){ if(is_dir($path)){ if(FALSE !== ($res = opendir($path))){ while(FALSE !== ($file = readdir($res))){ if($file == '.' || $file == '..'){ continue; } $subPath = $path . '/' . $file; if(is_dir($subPath)){ echo $subPath . "\r\n"; listDir($subPath); } else{ echo $subPath . "\r\n"; } } } } } 21、找出相对的目录,比如/a/b/c/d/e.php相对于/a/b/13/34/c.php是/c/d/ function ralativePath($a, $b){ $a = explode('/', dirname($a)); $b = explode('/', dirname($b)); $c = '/'; foreach ($a as $k=> $v){ if($v != $b[$k]){ $c .= $v . '/'; } } echo $c; } 22、快速找出url中php后缀 function get_ext($url){ $data = parse_url($url); return pathinfo($data['path'], PATHINFO_EXTENSION); } 23、正则题,使用正则抓取网页,以网页meta为utf8为准,若是抓取的网页编码为big5之类的,需要转化为utf8再收录 function preg_meta($meta){ $replacement = "\\1utf8\\6\\7"; $pattern = '#(<meta\s+http-equiv=(\'|"|)Content-Type(\'|"|)\s+content=(\'|"|)text/html; charset=)(\w+)(\'|"|)(>)#i'; return preg_replace($pattern, $replacement, $meta); } echo preg_meta("<meta http-equiv=Content-Type content='text/html; charset=big5'><META http-equiv=\"Content-Type\" content='text/html; charset=big5'>"); 24、不用php的反转函数倒序输出字符串,如abc,反序输出cba function revstring($str){ for($i=strlen($str)-1; $i>=0; $i--){ echo $str{$i}; } } revstring('abc'); 25、常见端口 TCP 21端口:FTP 文件传输服务 SSH 22端口:SSH连接linux服务器,通过SSH连接可以远程管理Linux等设备 TCP 23端口:TELNET 终端仿真服务 TCP 25端口:SMTP 简单邮件传输服务 UDP 53端口:DNS 域名解析服务 TCP 80端口:HTTP 超文本传输服务 TCP 110端口:POP3 “邮局协议版本3”使用的端口 TCP 443端口:HTTPS 加密的超文本传输服务 TCP 1521端口:Oracle数据库服务 TCP 1863端口:MSN Messenger的文件传输功能所使用的端口 TCP 3389端口:Microsoft RDP 微软远程桌面使用的端口 TCP 5631端口:Symantec pcAnywhere 远程控制数据传输时使用的端口 UDP 5632端口:Symantec pcAnywhere 主控端扫描被控端时使用的端口 TCP 5000端口:MS SQL Server使用的端口 UDP 8000端口:腾讯QQ 26、linux常用的命令 top linux进程实时监控 ps 在Linux中是查看进程的命令。ps查看正处于Running的进程 mv 为文件或目录改名或将文件由一个目录移入另一个目录中。 find 查找文件 df 可显示所有文件系统对i节点和磁盘块的使用情况。 cat 打印文件类容 chmod 变更文件或目录的权限 chgrp 文件或目录的权限的掌控以拥有者及所诉群组来管理。可以使用chgrp指令取变更文件与目录所属群组 grep 是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来。 wc 为统计指定文件中的字节数、字数、行数,并将统计结果显示输出 27、对于大流量的网站,您采用什么样的方法来解决访问量问题 首先,确认服务器硬件是否足够支持当前的流量 其次,优化数据库访问。 第三,禁止外部的盗链。 第四,控制大文件的下载。 第五,使用不同主机分流主要流量 第六,使用流量分析统计软件 28、$_SERVER常用的字段 $_SERVER['PHP_SELF'] #当前正在执行脚本的文件名 $_SERVER['SERVER_NAME'] #当前运行脚本所在服务器主机的名称 $_SERVER['REQUEST_METHOD'] #访问页面时的请求方法。例如:“GET”、“HEAD”,“POST”,“PUT” $_SERVER['QUERY_STRING'] #查询(query)的字符串 $_SERVER['HTTP_HOST'] #当前请求的 Host: 头部的内容 $_SERVER['HTTP_REFERER'] #链接到当前页面的前一页面的 URL 地址 $_SERVER['REMOTE_ADDR'] #正在浏览当前页面用户的 IP 地址 $_SERVER['REMOTE_HOST'] #正在浏览当前页面用户的主机名 $_SERVER['SCRIPT_FILENAME'] #当前执行脚本的绝对路径名 $_SERVER['SCRIPT_NAME'] #包含当前脚本的路径。这在页面需要指向自己时非常有用 $_SERVER['REQUEST_URI'] #访问此页面所需的 URI。例如,“/index.html” 29、安装php扩展 进入扩展的目录 phpize命令得到configure文件 ./configure --with-php-config=/usr/local/php/bin/php-config make & make install 在php.ini中加入扩展名称.so 重启web服务器(nginx/apache) 30、php-fpm与nginx PHP-FPM也是一个第三方的FastCGI进程管理器,它是作为PHP的一个补丁来开发的,在安装的时候也需要和PHP源码一起编译,也就是说PHP-FPM被编译到PHP内核中,因此在处理性能方面更加优秀;同时它在处理高并发方面也比spawn-fcgi引擎好很多,因此,推荐Nginx+PHP/PHP-FPM这个组合对PHP进行解析。 FastCGI 的主要优点是把动态语言和HTTP Server分离开来,所以Nginx与PHP/PHP-FPM经常被部署在不同的服务器上,以分担前端Nginx服务器的压力,使Nginx专一处理静态请求和转发动态请求,而PHP/PHP-FPM服务器专一解析PHP动态请求 #fastcgi FastCGI是一个可伸缩地、高速地在HTTP server和动态脚本语言间通信的接口。多数流行的HTTP server都支持FastCGI,包括Apache、Nginx和lighttpd等,同时,FastCGI也被许多脚本语言所支持,其中就有PHP。 FastCGI是从CGI发展改进而来的。传统CGI接口方式的主要缺点是性能很差,因为每次HTTP服务器遇到动态程序时都需要重新启动脚本解析器来执行解析,然后结果被返回给HTTP服务器。这在处理高并发访问时,几乎是不可用的。另外传统的CGI接口方式安全性也很差,现在已经很少被使用了。 FastCGI接口方式采用C/S结构,可以将HTTP服务器和脚本解析服务器分开,同时在脚本解析服务器上启动一个或者多个脚本解析守护进程。当HTTP服务器每次遇到动态程序时,可以将其直接交付给FastCGI进程来执行,然后将得到的结果返回给浏览器。这种方式可以让HTTP服务器专一地处理静态请求或者将动态脚本服务器的结果返回给客户端,这在很大程度上提高了整个应用系统的性能。 Nginx+FastCGI运行原理 Nginx不支持对外部程序的直接调用或者解析,所有的外部程序(包括PHP)必须通过FastCGI接口来调用。FastCGI接口在Linux下是socket,(这个socket可以是文件socket,也可以是ip socket)。为了调用CGI程序,还需要一个FastCGI的wrapper(wrapper可以理解为用于启动另一个程序的程序),这个wrapper绑定在某个固定socket上,如端口或者文件socket。当Nginx将CGI请求发送给这个socket的时候,通过FastCGI接口,wrapper接纳到请求,然后派生出一个新的线程,这个线程调用解释器或者外部程序处理脚本并读取返回数据;接着,wrapper再将返回的数据通过FastCGI接口,沿着固定的socket传递给Nginx;最后,Nginx将返回的数据发送给客户端,这就是Nginx+FastCGI的整个运作过程。 31、ajax全称“Asynchronous Javascript And XML”(异步JavaScript和XML)

小川游鱼 2019-12-02 01:41:29 0 浏览量 回答数 0

问题

【阿里云产品公测】简单日志服务SLS使用评测含教程

mr_wid 2019-12-01 21:08:11 36639 浏览量 回答数 20

回答

首先要提出来的是安全问题。本节讨论的思想如果没有一些额外的安全和认知机制的话会很糟糕。 也就是说,我们的主要目的是深入分析Python的import语句机制。 如果你理解了本节内部原理,你就能够为其他任何目的而自定义import。 有了这些,让我们继续向前走。 本节核心是设计导入语句的扩展功能。有很多种方法可以做这个, 不过为了演示的方便,我们开始先构造下面这个Python代码结构: testcode/ spam.py fib.py grok/ __init__.py blah.py 这些文件的内容并不重要,不过我们在每个文件中放入了少量的简单语句和函数, 这样你可以测试它们并查看当它们被导入时的输出。例如: # spam.py print("I'm spam") def hello(name): print('Hello %s' % name) # fib.py print("I'm fib") def fib(n): if n < 2: return 1 else: return fib(n-1) + fib(n-2) # grok/__init__.py print("I'm grok.__init__") # grok/blah.py print("I'm grok.blah") 这里的目的是允许这些文件作为模块被远程访问。 也许最简单的方式就是将它们发布到一个web服务器上面。在testcode目录中像下面这样运行Python: bash % cd testcode bash % python3 -m http.server 15000 Serving HTTP on 0.0.0.0 port 15000 ... 服务器运行起来后再启动一个单独的Python解释器。 确保你可以使用 urllib 访问到远程文件。例如: >>> from urllib.request import urlopen >>> u = urlopen('http://localhost:15000/fib.py') >>> data = u.read().decode('utf-8') >>> print(data) # fib.py print("I'm fib") def fib(n): if n < 2: return 1 else: return fib(n-1) + fib(n-2) >>> 从这个服务器加载源代码是接下来本节的基础。 为了替代手动的通过 urlopen() 来收集源文件, 我们通过自定义import语句来在后台自动帮我们做到。 加载远程模块的第一种方法是创建一个显式的加载函数来完成它。例如: import imp import urllib.request import sys def load_module(url): u = urllib.request.urlopen(url) source = u.read().decode('utf-8') mod = sys.modules.setdefault(url, imp.new_module(url)) code = compile(source, url, 'exec') mod.__file__ = url mod.__package__ = '' exec(code, mod.__dict__) return mod 这个函数会下载源代码,并使用 compile() 将其编译到一个代码对象中, 然后在一个新创建的模块对象的字典中来执行它。下面是使用这个函数的方式: >>> fib = load_module('http://localhost:15000/fib.py') I'm fib >>> fib.fib(10) 89 >>> spam = load_module('http://localhost:15000/spam.py') I'm spam >>> spam.hello('Guido') Hello Guido >>> fib <module 'http://localhost:15000/fib.py' from 'http://localhost:15000/fib.py'> >>> spam <module 'http://localhost:15000/spam.py' from 'http://localhost:15000/spam.py'> >>> 正如你所见,对于简单的模块这个是行得通的。 不过它并没有嵌入到通常的import语句中,如果要支持更高级的结构比如包就需要更多的工作了。 一个更酷的做法是创建一个自定义导入器。第一种方法是创建一个元路径导入器。如下: # urlimport.py import sys import importlib.abc import imp from urllib.request import urlopen from urllib.error import HTTPError, URLError from html.parser import HTMLParser # Debugging import logging log = logging.getLogger(__name__) # Get links from a given URL def _get_links(url): class LinkParser(HTMLParser): def handle_starttag(self, tag, attrs): if tag == 'a': attrs = dict(attrs) links.add(attrs.get('href').rstrip('/')) links = set() try: log.debug('Getting links from %s' % url) u = urlopen(url) parser = LinkParser() parser.feed(u.read().decode('utf-8')) except Exception as e: log.debug('Could not get links. %s', e) log.debug('links: %r', links) return links class UrlMetaFinder(importlib.abc.MetaPathFinder): def __init__(self, baseurl): self._baseurl = baseurl self._links = { } self._loaders = { baseurl : UrlModuleLoader(baseurl) } def find_module(self, fullname, path=None): log.debug('find_module: fullname=%r, path=%r', fullname, path) if path is None: baseurl = self._baseurl else: if not path[0].startswith(self._baseurl): return None baseurl = path[0] parts = fullname.split('.') basename = parts[-1] log.debug('find_module: baseurl=%r, basename=%r', baseurl, basename) # Check link cache if basename not in self._links: self._links[baseurl] = _get_links(baseurl) # Check if it's a package if basename in self._links[baseurl]: log.debug('find_module: trying package %r', fullname) fullurl = self._baseurl + '/' + basename # Attempt to load the package (which accesses __init__.py) loader = UrlPackageLoader(fullurl) try: loader.load_module(fullname) self._links[fullurl] = _get_links(fullurl) self._loaders[fullurl] = UrlModuleLoader(fullurl) log.debug('find_module: package %r loaded', fullname) except ImportError as e: log.debug('find_module: package failed. %s', e) loader = None return loader # A normal module filename = basename + '.py' if filename in self._links[baseurl]: log.debug('find_module: module %r found', fullname) return self._loaders[baseurl] else: log.debug('find_module: module %r not found', fullname) return None def invalidate_caches(self): log.debug('invalidating link cache') self._links.clear() # Module Loader for a URL class UrlModuleLoader(importlib.abc.SourceLoader): def __init__(self, baseurl): self._baseurl = baseurl self._source_cache = {} def module_repr(self, module): return '<urlmodule %r from %r>' % (module.__name__, module.__file__) # Required method def load_module(self, fullname): code = self.get_code(fullname) mod = sys.modules.setdefault(fullname, imp.new_module(fullname)) mod.__file__ = self.get_filename(fullname) mod.__loader__ = self mod.__package__ = fullname.rpartition('.')[0] exec(code, mod.__dict__) return mod # Optional extensions def get_code(self, fullname): src = self.get_source(fullname) return compile(src, self.get_filename(fullname), 'exec') def get_data(self, path): pass def get_filename(self, fullname): return self._baseurl + '/' + fullname.split('.')[-1] + '.py' def get_source(self, fullname): filename = self.get_filename(fullname) log.debug('loader: reading %r', filename) if filename in self._source_cache: log.debug('loader: cached %r', filename) return self._source_cache[filename] try: u = urlopen(filename) source = u.read().decode('utf-8') log.debug('loader: %r loaded', filename) self._source_cache[filename] = source return source except (HTTPError, URLError) as e: log.debug('loader: %r failed. %s', filename, e) raise ImportError("Can't load %s" % filename) def is_package(self, fullname): return False # Package loader for a URL class UrlPackageLoader(UrlModuleLoader): def load_module(self, fullname): mod = super().load_module(fullname) mod.__path__ = [ self._baseurl ] mod.__package__ = fullname def get_filename(self, fullname): return self._baseurl + '/' + '__init__.py' def is_package(self, fullname): return True # Utility functions for installing/uninstalling the loader _installed_meta_cache = { } def install_meta(address): if address not in _installed_meta_cache: finder = UrlMetaFinder(address) _installed_meta_cache[address] = finder sys.meta_path.append(finder) log.debug('%r installed on sys.meta_path', finder) def remove_meta(address): if address in _installed_meta_cache: finder = _installed_meta_cache.pop(address) sys.meta_path.remove(finder) log.debug('%r removed from sys.meta_path', finder) 下面是一个交互会话,演示了如何使用前面的代码: >>> # importing currently fails >>> import fib Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: No module named 'fib' >>> # Load the importer and retry (it works) >>> import urlimport >>> urlimport.install_meta('http://localhost:15000') >>> import fib I'm fib >>> import spam I'm spam >>> import grok.blah I'm grok.__init__ I'm grok.blah >>> grok.blah.__file__ 'http://localhost:15000/grok/blah.py' >>> 这个特殊的方案会安装一个特别的查找器 UrlMetaFinder 实例, 作为 sys.meta_path 中最后的实体。 当模块被导入时,会依据 sys.meta_path 中的查找器定位模块。 在这个例子中,UrlMetaFinder 实例是最后一个查找器方案, 当模块在任何一个普通地方都找不到的时候就触发它。 作为常见的实现方案,UrlMetaFinder 类包装在一个用户指定的URL上。 在内部,查找器通过抓取指定URL的内容构建合法的链接集合。 导入的时候,模块名会跟已有的链接作对比。如果找到了一个匹配的, 一个单独的 UrlModuleLoader 类被用来从远程机器上加载源代码并创建最终的模块对象。 这里缓存链接的一个原因是避免不必要的HTTP请求重复导入。 自定义导入的第二种方法是编写一个钩子直接嵌入到 sys.path 变量中去, 识别某些目录命名模式。 在 urlimport.py 中添加如下的类和支持函数: # urlimport.py # ... include previous code above ... # Path finder class for a URL class UrlPathFinder(importlib.abc.PathEntryFinder): def __init__(self, baseurl): self._links = None self._loader = UrlModuleLoader(baseurl) self._baseurl = baseurl def find_loader(self, fullname): log.debug('find_loader: %r', fullname) parts = fullname.split('.') basename = parts[-1] # Check link cache if self._links is None: self._links = [] # See discussion self._links = _get_links(self._baseurl) # Check if it's a package if basename in self._links: log.debug('find_loader: trying package %r', fullname) fullurl = self._baseurl + '/' + basename # Attempt to load the package (which accesses __init__.py) loader = UrlPackageLoader(fullurl) try: loader.load_module(fullname) log.debug('find_loader: package %r loaded', fullname) except ImportError as e: log.debug('find_loader: %r is a namespace package', fullname) loader = None return (loader, [fullurl]) # A normal module filename = basename + '.py' if filename in self._links: log.debug('find_loader: module %r found', fullname) return (self._loader, []) else: log.debug('find_loader: module %r not found', fullname) return (None, []) def invalidate_caches(self): log.debug('invalidating link cache') self._links = None # Check path to see if it looks like a URL _url_path_cache = {} def handle_url(path): if path.startswith(('http://', 'https://')): log.debug('Handle path? %s. [Yes]', path) if path in _url_path_cache: finder = _url_path_cache[path] else: finder = UrlPathFinder(path) _url_path_cache[path] = finder return finder else: log.debug('Handle path? %s. [No]', path) def install_path_hook(): sys.path_hooks.append(handle_url) sys.path_importer_cache.clear() log.debug('Installing handle_url') def remove_path_hook(): sys.path_hooks.remove(handle_url) sys.path_importer_cache.clear() log.debug('Removing handle_url') 要使用这个路径查找器,你只需要在 sys.path 中加入URL链接。例如: >>> # Initial import fails >>> import fib Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: No module named 'fib' >>> # Install the path hook >>> import urlimport >>> urlimport.install_path_hook() >>> # Imports still fail (not on path) >>> import fib Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: No module named 'fib' >>> # Add an entry to sys.path and watch it work >>> import sys >>> sys.path.append('http://localhost:15000') >>> import fib I'm fib >>> import grok.blah I'm grok.__init__ I'm grok.blah >>> grok.blah.__file__ 'http://localhost:15000/grok/blah.py' >>> 关键点就是 handle_url() 函数,它被添加到了 sys.path_hooks 变量中。 当 sys.path 的实体被处理时,会调用 sys.path_hooks 中的函数。 如果任何一个函数返回了一个查找器对象,那么这个对象就被用来为 sys.path 实体加载模块。 远程模块加载跟其他的加载使用方法几乎是一样的。例如: >>> fib <urlmodule 'fib' from 'http://localhost:15000/fib.py'> >>> fib.__name__ 'fib' >>> fib.__file__ 'http://localhost:15000/fib.py' >>> import inspect >>> print(inspect.getsource(fib)) # fib.py print("I'm fib") def fib(n): if n < 2: return 1 else: return fib(n-1) + fib(n-2) >>>

哦哦喔 2020-04-17 17:11:05 0 浏览量 回答数 0
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 SQL审核 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站 人工智能 阿里云云栖号 云栖号案例 云栖号直播