成都建设网站企业电话/上海网站建设开发公司
引言
在编写和维护Java应用程序时,内存泄漏是一个重要的问题,可能导致性能下降和不稳定性。本文将介绍内存泄漏的概念,为什么它在Java应用程序中如此重要,并明确本文的目标,即识别、预防和解决内存泄漏问题。
内存泄漏的概念
内存泄漏是指应用程序中分配的内存(通常是堆内存)在不再需要时未能正确释放。这些未释放的内存块会积累,最终导致应用程序消耗过多的内存资源,甚至可能导致应用程序崩溃或变得非常缓慢。内存泄漏通常是由于不正确的对象引用管理或资源未正确释放而导致的。
为什么内存泄漏重要
内存泄漏对Java应用程序的重要性不容忽视,因为它可能导致以下问题:
-
性能下降: 内存泄漏会导致应用程序占用更多内存,因此可能会导致性能下降,尤其是在长时间运行的应用程序中。
-
不稳定性: 内存泄漏可能会导致内存耗尽,从而导致应用程序崩溃或变得不稳定。
-
资源浪费: 未释放的内存块是资源的浪费,这些资源本应该可供其他部分或其他应用程序使用。
-
难以调试: 内存泄漏通常难以追踪和调试,因为它们不会引发明显的错误或异常,而是在应用程序长时间运行后才变得明显。
识别内存泄漏
在本节中,我们将讨论如何识别内存泄漏的迹象和常见的内存泄漏模式。了解这些迹象和模式可以帮助您更早地发现潜在的内存泄漏问题,从而减少其影响。
内存泄漏的迹象
以下是一些可能表明应用程序存在内存泄漏的迹象:
-
内存占用不断增加: 观察应用程序的内存占用情况。如果内存占用持续增加而不释放,可能存在内存泄漏。
-
长时间运行后性能下降: 如果应用程序在运行一段时间后变得非常缓慢,这可能是内存泄漏的迹象。
-
频繁的垃圾回收: 如果垃圾回收发生得非常频繁,尤其是Full GC,这可能表明内存泄漏正在导致过多的对象被保留。
常见的内存泄漏模式
以下是一些常见的内存泄漏模式,这些模式可能会导致内存泄漏问题:
-
对象引用未释放: 对象引用被保留在内存中,即使它们不再需要。这可能是由于集合、缓存或静态变量等原因。
-
资源未释放: 资源,如文件句柄、数据库连接或网络连接,未正确关闭和释放。
-
匿名内部类: 匿名内部类可能会隐式持有对外部类的引用,导致外部类的对象无法被垃圾回收。
-
监听器注册: 注册的事件监听器未正确注销,导致被监听对象无法释放。
-
线程泄漏: 启动的线程未正确关闭或管理,导致线程泄漏。
监视工具和分析方法
为了帮助识别内存泄漏问题,您可以使用以下监视工具和分析方法:
-
内存分析器: 使用Java内存分析器工具,如MAT(Eclipse Memory Analyzer Tool)或VisualVM,来检查堆内存中的对象和引用关系。这些工具可以帮助您找到潜在的内存泄漏。
-
日志记录: 在应用程序中添加详细的日志记录,以便跟踪对象的创建和销毁。分析日志可以帮助您了解对象的生命周期。
-
性能监控工具: 使用性能监控工具来观察内存占用、垃圾回收频率和应用程序性能。这些工具可以帮助您及早发现内存泄漏问题。
预防内存泄漏
预防内存泄漏是最佳策略,因为一旦内存泄漏发生,就需要花费更多的时间来识别和解决问题。以下是一些预防内存泄漏的最佳实践,包括良好的对象引用管理和资源释放。
1. 良好的对象引用管理
内存泄漏通常与对象引用的不正确管理有关。以下是一些良好的对象引用管理实践:
-
弱引用和软引用: 对于临时性的对象引用,可以考虑使用Java中的弱引用(Weak Reference)或软引用(Soft Reference)。这些引用类型会在内存不足时被垃圾回收器更容易地回收。
-
及时清理引用: 当对象不再需要时,确保清理对该对象的引用,以便垃圾回收器可以正确回收它们。
-
避免静态集合: 避免在静态变量中存储对象引用,因为它们在整个应用程序的生命周期内都不会释放。
-
使用局部变量: 在方法内部使用局部变量来存储临时对象引用,方法结束时,这些引用会自动被销毁。
2. 资源释放
另一个常见的内存泄漏原因是未正确释放资源,如文件句柄、数据库连接或网络连接。以下是一些资源释放的最佳实践:
- 使用try-with-resources: 如果您使用Java 7或更高版本,可以使用try-with-resources语句来确保资源在使用后被正确关闭。例如,使用
try-with-resources
来管理文件IO:
try (FileInputStream fis = new FileInputStream("file.txt")) {// 处理文件内容
} catch (IOException e) {// 处理异常
}
- 手动关闭资源: 对于不支持try-with-resources的资源,如数据库连接,请确保在不再需要时手动关闭它们,通常在
finally
块中进行。
Connection connection = null;
try {connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password");// 使用连接执行数据库操作
} catch (SQLException e) {// 处理异常
} finally {if (connection != null) {try {connection.close();} catch (SQLException e) {// 处理异常}}
}
3. 垃圾回收器的帮助
Java的垃圾回收器负责回收不再使用的内存。虽然它们通常能够正确处理内存管理,但在某些情况下,您可以利用垃圾回收器的帮助来减少内存泄漏的风险。例如,使用弱引用和软引用可以让垃圾回收器更容易地回收这些对象。
常见的内存泄漏陷阱
在Java中,有一些常见的内存泄漏陷阱,可能会导致内存泄漏问题。在本节中,我们将探讨这些陷阱,并提供示例和详细解释。
1. 静态集合
静态集合,如静态List
、Map
或Set
,可以在整个应用程序生命周期内保留对象引用。如果您向静态集合中添加对象,并且不再需要这些对象,它们将永远不会被垃圾回收。
示例:
public class StaticCollectionLeak {private static List<Object> staticList = new ArrayList<>();public void addToStaticList(Object obj) {staticList.add(obj);}// 其他方法...
}
解决方法: 使用弱引用或软引用来管理静态集合中的对象引用,或者确保在不再需要对象时从静态集合中删除它们。
2. 匿名内部类
匿名内部类通常会隐式地持有对外部类的引用,这可能导致外部类的对象无法被垃圾回收。
示例:
public class LeakyOuter {private ActionListener listener;public void addListener() {listener = new ActionListener() {public void actionPerformed(ActionEvent e) {// 处理事件}};}// 其他方法...
}
在上面的示例中,匿名内部类ActionListener
持有对LeakyOuter
的引用,即使LeakyOuter
对象不再需要。
解决方法: 将外部类的引用传递给内部类时,使用弱引用或者手动取消对外部类的引用,以便外部类对象能够被垃圾回收。
3. 监听器注册
注册的事件监听器如果未正确注销,将会持续接收事件,导致相关对象无法被垃圾回收。
示例:
public class LeakyListener {private List<ActionListener> listeners = new ArrayList<>();public void addListener(ActionListener listener) {listeners.add(listener);}public void fireEvent() {ActionEvent event = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "Event");for (ActionListener listener : listeners) {listener.actionPerformed(event);}}// 其他方法...
}
如果不在适当的时候从listeners
中移除监听器,它们将继续持有对LeakyListener
的引用。
解决方法: 确保在不再需要监听器时,从监听器列表中移除它们,以便它们可以被垃圾回收。
4. 线程泄漏
如果启动的线程未正确关闭或管理,它们将继续运行,即使应用程序退出。
示例:
public class LeakyThread {public void startLeakyThread() {Thread thread = new Thread(new Runnable() {public void run() {// 执行任务}});thread.start();}// 其他方法...
}
在上面的示例中,启动的线程没有被显式关闭,因此即使应用程序退出,它仍然在运行。
解决方法: 确保在不再需要的线程上调用Thread
的interrupt
方法或者以其他方式停止线程,以便它们可以正确关闭。
在下一节中,我们将讨论解决内存泄漏问题的方法,包括手动资源清理、弱引用和软引用的使用。让我们继续深入了解这些方法!
内存泄漏解决方法
当识别到内存泄漏问题时,及早采取措施解决问题是至关重要的。在本节中,我们将讨论解决内存泄漏问题的方法,包括手动资源清理、弱引用和软引用的使用。
1. 手动资源清理
手动资源清理是一种最常见的解决内存泄漏问题的方法。它包括在对象不再需要时显式释放对资源的引用。这对于文件、数据库连接、网络连接等需要手动关闭的资源特别重要。
示例:
public class ResourceLeak {private Connection connection;public void openConnection() throws SQLException {connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password");}public void closeConnection() throws SQLException {if (connection != null) {connection.close();}}// 其他方法...
}
在上面的示例中,closeConnection
方法用于手动关闭数据库连接,确保在不再需要时释放资源。
2. 弱引用和软引用
Java提供了弱引用(Weak Reference)和软引用(Soft Reference)来帮助解决内存泄漏问题。这些引用类型不会阻止对象被垃圾回收。
- 弱引用(Weak Reference): 弱引用对象不会阻止其关联的对象被垃圾回收。当对象只有弱引用时,如果没有其他强引用指向它,垃圾回收器将尽快回收该对象。
WeakReference<Object> weakReference = new WeakReference<>(someObject);
- 软引用(Soft Reference): 软引用对象也不会阻止其关联的对象被垃圾回收,但垃圾回收器会在内存不足时,才回收这些对象。这对于实现高速缓存等场景很有用。
SoftReference<Object> softReference = new SoftReference<>(someObject);
使用弱引用和软引用时,需要小心确保在需要时仍然存在对对象的有效引用,以免对象在不再需要时被过早地回收。
3. 代码审查和测试
代码审查和测试是解决内存泄漏问题的关键步骤。在开发和维护应用程序时,定期审查代码以查找潜在的内存泄漏问题,并进行测试以验证内存管理的正确性。
-
静态代码分析工具: 使用静态代码分析工具来检测代码中的潜在内存泄漏问题。这些工具可以识别未关闭的资源、未释放的对象引用等问题。
-
单元测试和集成测试: 创建单元测试和集成测试,以验证内存管理的正确性。测试应覆盖涉及资源释放和对象引用管理的代码路径。
4. 监控和日志记录
监控和日志记录是及早发现内存泄漏问题的关键。使用性能监控工具来观察内存占用和垃圾回收频率,并添加详细的日志记录以跟踪对象的生命周期。
-
性能监控工具: 使用性能监控工具来观察内存占用、垃圾回收频率和应用程序性能。这些工具可以帮助您及早发现内存泄漏问题。
-
日志记录: 在应用程序中添加详细的日志记录,以便跟踪对象的创建和销毁。分析日志可以帮助您了解对象的生命周期。
工具和技术
在本节中,我们将介绍用于检测和调试内存泄漏的工具和技术。这些工具可以帮助您更轻松地定位和解决内存泄漏问题。
1. 内存分析器工具
内存分析器工具是识别和解决内存泄漏问题的强大工具。以下是一些常用的内存分析器工具:
-
MAT(Eclipse Memory Analyzer Tool): MAT是一个免费的Java内存分析器,可帮助您分析堆转储文件并识别内存泄漏问题。它提供了直观的界面,用于查看对象引用关系和检测泄漏。
-
VisualVM: VisualVM是Java虚拟机监视和故障排除工具,它具有内存分析功能。您可以使用VisualVM连接到正在运行的Java应用程序,分析堆内存,并查找潜在的内存泄漏问题。
-
YourKit Java Profiler: YourKit是一款商业的Java性能分析工具,具有内存分析功能。它可以帮助您识别内存泄漏,并提供性能优化建议。
2. Java虚拟机选项
Java虚拟机(JVM)提供了一些选项,可用于监视和调试内存泄漏问题:
-
-Xmx和-Xms: 使用这些选项可以设置Java堆内存的最大和初始大小。通过监视内存使用情况,您可以确定是否存在内存泄漏。
-
-XX:+HeapDumpOnOutOfMemoryError: 当发生OutOfMemoryError时,JVM会生成堆转储文件。这个文件可以用于后续的内存分析。
-
-XX:HeapDumpPath: 使用这个选项可以指定堆转储文件的存储路径。
3. 实际案例分析
学习和理解实际内存泄漏案例分析是解决内存泄漏问题的有力工具。通过研究实际问题,您可以更好地了解内存泄漏的根本原因和解决方法。
以下是一些常见的内存泄漏案例:
-
数据库连接未关闭: 如果应用程序未正确关闭数据库连接,连接池中的连接可能不会被释放,导致内存泄漏。
-
缓存未清理: 对象被存储在缓存中,但没有过期或被删除,导致缓存中的对象持续增加。
-
监听器未注销: 注册的事件监听器未正确注销,导致监听对象无法释放。
-
对象引用未释放: 对象引用被保留在集合中,即使不再需要,也无法被垃圾回收。
通过分析这些案例并查找解决方案,您可以更好地了解如何识别和解决内存泄漏问题。
4. 性能测试和比较
进行性能测试和比较是评估内存泄漏问题严重性的重要步骤。通过在有内存泄漏和无内存泄漏的情况下运行应用程序,并比较内存使用和性能差异,可以更好地了解内存泄漏对应用程序的影响。
总结
本文涵盖了内存泄漏问题在Java应用程序中的重要性以及如何识别、预防和解决这些问题。以下是本文的关键观点和建议总结:
-
内存泄漏的重要性: 内存泄漏是Java应用程序中常见的问题之一,可能导致内存占用不断增加,性能下降,甚至应用程序崩溃。因此,及早发现和解决内存泄漏问题至关重要。
-
识别内存泄漏: 内存泄漏的迹象包括内存占用不断增加、长时间运行后性能下降和频繁的垃圾回收。常见的内存泄漏模式包括对象引用未释放、资源未释放、匿名内部类、监听器注册和线程泄漏。
-
预防内存泄漏: 良好的对象引用管理和资源释放是预防内存泄漏的关键。使用弱引用和软引用来管理临时性引用,并避免静态集合存储对象引用。
-
常见陷阱: 常见的内存泄漏陷阱包括静态集合、匿名内部类、监听器注册和线程泄漏。了解这些陷阱有助于避免它们。
-
解决方法: 解决内存泄漏问题的方法包括手动资源清理、使用弱引用和软引用、代码审查和测试,以及监控和日志记录。
-
工具和技术: 内存分析器工具(如MAT和VisualVM)、Java虚拟机选项、实际案例分析、性能测试和比较是用于检测和调试内存泄漏的重要工具和技术。
更多内容请参考 www.flydean.com
最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!
相关文章:

深入探讨Java面试中内存泄漏:如何识别、预防和解决
引言 在编写和维护Java应用程序时,内存泄漏是一个重要的问题,可能导致性能下降和不稳定性。本文将介绍内存泄漏的概念,为什么它在Java应用程序中如此重要,并明确本文的目标,即识别、预防和解决内存泄漏问题。 内存泄…...

win10 安装.net framework 3.5,错误代码0x8024401C
win10 安装.net framework 3.5,错误代码0x8024401C 参考链接:https://www.gxlsystem.com/diannaowenti-386775.html 解决方法如下,cmd中执行: net stop wuauserv reg delete HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\W…...

杂记 | Langchain中few-shot提示词模板的使用(给提示词添加示例)
文章目录 01 普通的提示词模板02 few-shot提示词模板 Langchain是一个集成多个大语言模型的开源框架,可以使用它来快速开发大语言模型应用。 本文的代码使用到的模块: from typing import List, Dict from langchain import PromptTemplate, FewShotPr…...

SVN -基础
SVN - 基础 概念操作步骤开发实际经验 概念 带SVN路径 有隐藏文件,记录repo的一些信息,与repo进行关联,可以与repo进行同步 不带SVN路径 只是单纯的文件,与repo独立 操作步骤 checkout 具有路径 URLcheckout dir 输出目标文件夹…...

MySQL基础终端命令与Python简单操作MySQL
文章目录 MySQL终端命令1. 进入mysql2. 创建数据库3. 选择数据库4. 创建数据表1. 主键约束2. 外键约束3. 非空约束4. 唯一约束5. 使用默认约束6. 设置id为自增列 5. 查看数据表6. 修改数据表1. 修改表名2. 修改表的字段类型3. 修改表的字段名4. 为表添加字段5. 删除字段6. 调整…...

编译原理.龙书学习1
第一章: 编译器:将程序翻译成一种能够被计算机执行的形式 解释器:解释器直接利用用户提供的输入执行源程序中指定的操作 一个编译器的结构 编译器将源程序映射为语义上等价的目标程序,这个映射过程由两部分组成:分析…...

anaconda安装完成之后输入conda -V没有反应
anaconda安装完成后,conda没有反应 vim ~/.bashrc后面添加内容 # added by Anaconda3 5.3.0 installer # >>> conda init >>> # !! Contents within this block are managed by conda init !! __conda_setup"$(CONDA_REPORT_ERRORSfalse /u…...

netty报文解析之粘包半包问题
粘包问题 Netty 的粘包问题是指在网络传输过程中,由于 TCP 协议本身的特点,导致发送方发送的若干个小数据包被接收方合并成了一个大数据包。这种情况称为粘包。 TCP 协议是面向流的协议,没有数据边界,发送方发送的数据可能会被分…...

EasyCode整合mybatis-plus的配置
文章目录 entitymapper.javamapper.xmlserviceserviceImplcontroller 这篇文章不教你如何安装和使用EasyCode,只是贴出可以使用的配置。 具体EasyCode的使用可以查看其它的文章。 entity ##导入宏定义 $!{define.vm}##保存文件(宏定义) #sa…...

实施预测性维护解决方案的挑战及PreMaint的应对方法
前面我们介绍了企业选择预测性维护解决方案的常见问题和PreMaint的策略,本期我们将带来实施过程中可能会遇到的挑战,以及如何通过PreMaint来应对这些挑战,以实现可靠的预测性维护。 随着工业技术的不断进步,预测性维护作为一种先进…...

1. js中let、var、const定义变量区别与方式
1 声明语法 var upperA A; let upperB B; const upperC C; 只声明不初始化的结果,【 const定义的常量不可以修改,而且必须初始化】 // var 声明变量 var upperA; console.log(打印大写的A:%s, upperA); // 结果:打印大写的A&am…...

【STM32学习】I2C通信协议 | OLED屏
🐱作者:一只大喵咪1201 🐱专栏:《STM32学习》 🔥格言:你只管努力,剩下的交给时间! 今天需要将代码烧录到开发板中,本喵默认大家都会创建工程,以及进行基本的…...

Nvme Spec 第一章节学习
Nvme Express Base Specification 第一章 简介 1.1概述 NVM ExpressTM(NVMeTM)接口允许主机软件与非易失性存储器子系统通信。 此接口针对企业和客户端固态驱动器进行了优化,通常作为寄存器级接口连接到PCI Express接口。 注:在…...

第一章:最新版零基础学习 PYTHON 教程(第九节 - Python 语句中的 – 多行语句)
Python 中的语句: 在Python中,语句是Python解释器可以读取和执行的逻辑命令。它可能是Python 中的赋值语句或表达式。 Python 中的多行语句: 在Python中,语句通常写成一行,每行的最后一个字符是换行符。要将语句扩展到一行或多行,我们可以使用大括号 {}、圆括号 ()、方…...

kafka 3.0 离线安装
1.安装zookeeper 解压apache-zookeeper-3.8.0-bin.tar.gz到指定目录,复制conf目录下zoo_sample.cfg到zoo.cfg,并修改配置。 # The number of milliseconds of each tick tickTime=2000 # The number of ticks that the initial # synchronization phase can take initLimit…...

MySQL数据库入门到精通2--基础篇(函数,约束,多表查询,事务)
3. 函数 函数 是指一段可以直接被另一段程序调用的程序或代码。MySQL中的函数主要分为以下四类: 字符串函数、数值函数、日期函数、流程函数。 3.1 字符串函数 MySQL中内置了很多字符串函数,常用的几个如下: 演示如下: A. con…...

c-数据在内存中的存储-day7
...

3D大模型如何轻量化?试试HOOPS Communicator,轻松读取10G超大模型!
随着计算机技术的不断发展,3D模型在各行各业中的应用越来越广泛。然而,随着模型的复杂性和规模不断增加,处理和浏览超大型3D模型变得越来越具有挑战性。本文将探讨如何轻量化3D大模型,以及如何使用HOOPS Communicator来读取和浏览…...

go并发操作且限制数量
使用管道chan func returnNum() int64 {return time.Now().Unix() } func main() {threadAmount : runtime.GOMAXPROCS(0)if threadAmount < 2 {threadAmount 2}fmt.Println(threadAmount)threadChan : make(chan int, threadAmount)defer close(threadChan)for {for i :…...

AI深度学习-卷积神经网络000
文章目录 前言1.什么是深度学习2.语义分割与实例分割概述3.什么是卷积?4.Unet网络 前言 本栏目,主要为深度学习保姆教程。 主要通过B站视频整理而来: 深度学习保姆级教学 Unet语义分割视觉三维重建算法 1.什么是深度学习 深度学习保姆级教…...

网站有反爬机制就爬不了数据?那是你不会【反】反爬
目录 前言 一、什么是代理IP 二、使用代理IP反反爬 1.获取代理IP 2.设置代理IP 3.验证代理IP 4.设置代理池 5.定时更新代理IP 三、反反爬案例 1.分析目标网站 2.爬取目标网站 四、总结 前言 爬虫技术的不断发展,使得许多网站都采取了反爬机制ÿ…...

2023华为杯研究生数学建模C题分析
完整的分析查看文末名片获取! 问题一 在每个评审阶段,作品通常都是随机分发的,每份作品需要多位评委独立评审。为了增加不同评审专家所给成绩之间的可比性,不同专家评审的作品集合之间应有一些交集。但有的交集大了,则…...

第三天:实现网络编程基于tcp/udp协议在Ubuntu与gec6818开发板之间双向通信
互联网地址 每一台设备接入互联网后,都会举报一个唯一的地址编号 IP地址 INTERNET地址 internet地址 :它是协议上的一个逻辑地址 目前来说,我们主要的IP地址有两类 IPV4 IPV6 IPV4 其实就是使用一个32bit整数作为IP IPV6 其实就是使用一…...

【MediaSoup---源码篇】(三)Transport
概述 RTC::Transport是mediasoup中的一个重要概念,它用于在mediasoup与客户端之间传输实时音视频数据。 Transport继承着众多的类,主要用于Transport的整体感知 class Transport : public RTC::Producer::Listener,public RTC::Consumer::Listener,publ…...

爱分析《商业智能最佳实践案例》
近日,国内知名数字化市场研究咨询机构爱分析发布《2023爱分析商业智能最佳实践案例》,此评选活动面向落地商业智能的各行企业和商业智能厂商,以第三方专业视角深入调研,评选出具有参考价值的创新案例。永达汽车集团与数聚股份合作…...

golang:context
context作用 goroutine的退出机制 多个goroutine都是平行的被调度的,多个goroutine如何协调工作涉及通信、同步、通知和退出 通信:goroutine之间的通信同步chan通道 同步:不带缓冲的chan提供了一个天然的同步等待机制。通过WaitGroup也可以…...

探讨代理IP与Socks5代理在跨界电商中的网络安全应用
在数字化时代,跨界电商已经成为了商业世界中的一大趋势。然而,跨越国界的电商活动也伴随着网络安全挑战。本文将讨论如何利用代理IP和Socks5代理技术来提高跨界电商中的网络安全,同时也探讨了与游戏相关的爬虫应用。 1. 代理IP和Socks5代理的…...

Guava Cache介绍-面试用
一、Guava Cache简介 1、简介 Guava Cache是本地缓存,数据读写都在一个进程内,相对于分布式缓存redis,不需要网络传输的过程,访问速度很快,同时也受到 JVM 内存的制约,无法在数据量较多的场景下使用。 基…...

ARM 汇编指令作业(求公约数、for循环实现1-100之间和、从SVC模式切换到user模式简单写法)
1、求两个数最大公约数 .text .globl _start_start:mov r0, #9mov r1, #15 Loop: 循环cmp r0,r1 比较r0和r1的大小beq stop 当r0和r1相等时,跳到stop标签subhi r0,r0,r1 r0-r1>0 时,证明r0>r1,将r0-r1的值赋给r0&…...

Go - 【字符串,数组,哈希表】常用操作
一. 字符串 字符串长度: s : "hello" l : len(s) fmt.Println(l) // 输出 5遍历字符串: s : "hello" for i, c : range s {fmt.Printf("%d:%c ", i, c) } // 输出:0:h 1:e 2:l 3:l 4:ofor i : 0; i < le…...