<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>编程代码归档 - 帝讯博客</title>
	<atom:link href="https://www.dixunblog.cn/category/jishushare/code/feed" rel="self" type="application/rss+xml" />
	<link>https://www.dixunblog.cn/category/jishushare/code</link>
	<description>致力于打造专业的互联网资讯平台</description>
	<lastBuildDate>Mon, 30 Mar 2026 03:48:46 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>

<image>
	<url>https://cdn.hyclive.cn/dixunblog/2025/12/cropped-ico-32x32.png</url>
	<title>编程代码归档 - 帝讯博客</title>
	<link>https://www.dixunblog.cn/category/jishushare/code</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Python 网络爬虫入门实战 &#8211; 实战篇</title>
		<link>https://www.dixunblog.cn/1455.html</link>
					<comments>https://www.dixunblog.cn/1455.html#respond</comments>
		
		<dc:creator><![CDATA[小编]]></dc:creator>
		<pubDate>Mon, 30 Mar 2026 02:05:58 +0000</pubDate>
				<category><![CDATA[技术教程]]></category>
		<category><![CDATA[编程代码]]></category>
		<category><![CDATA[Python 教程]]></category>
		<category><![CDATA[python-crawler]]></category>
		<category><![CDATA[代码教程]]></category>
		<guid isPermaLink="false">https://www.dixunblog.cn/1455.html</guid>

					<description><![CDATA[<p>欢迎来到今天的 Python 实战教程！今天我们来学习 Python 网络爬虫入门实战。</p>
<p>一、环境准备</p>
<p><code class="language-bash">pip install requests beautifulsoup4 lxml</p>
<p>二、基础请求</p>
<p>&#60;code class=&#34;language-python...</p>
<p><a href="https://www.dixunblog.cn/1455.html">Python 网络爬虫入门实战 &#8211; 实战篇</a>最先出现在<a href="https://www.dixunblog.cn">帝讯博客</a>。</p>
]]></description>
										<content:encoded><![CDATA[<p>欢迎来到今天的 Python 实战教程！今天我们来学习 Python 网络爬虫入门实战。</p>
<h2><img fetchpriority="high" decoding="async" class="alignnone size-full wp-image-1457" src="http://cdn.hyclive.cn/dixunblog/2026/03/生成-Python-爬虫入门实战图片.png" alt="" width="2730" height="1535" /></h2>
<h2>一、环境准备</h2>
<pre><code class="language-bash">pip install requests beautifulsoup4 lxml</code></pre>
<h2>二、基础请求</h2>
<pre><code class="language-python">import requests

# GET 请求
response = requests.get('https://www.example.com')
print(response.status_code)
print(response.text)</code></pre>
<h2>三、解析 HTML</h2>
<pre><code class="language-python">from bs4 import BeautifulSoup

html = '''</code></pre>
<h1>标题</h1>
<pre><code class="language-python"></code></pre>
<p>&#8221;&#8217; soup = BeautifulSoup(html, &#8216;lxml&#8217;) print(soup.h1.text)</p>
<pre><code class="language-python"></code></pre>
<h2>四、实战示例</h2>
<pre><code class="language-python"># 爬取新闻标题
import requests
from bs4 import BeautifulSoup

url = 'https://news.example.com'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'lxml')

headlines = soup.find_all('h2', class_='headline')
for h in headlines:
    print(h.text)</code></pre>
<h2>五、注意事项</h2>
<ol>
<li>遵守 robots.txt 协议</li>
<li>控制请求频率</li>
<li>使用 User-Agent</li>
<li>合法合规使用数据</li>
</ol>
<h2>六、总结</h2>
<p>网络爬虫是 Python 实战的重要应用。建议多实践。</p>
<hr />
<p><em>关注我们获取更多 Python 实战教程！</em></p>
<p><a href="https://www.dixunblog.cn/1455.html">Python 网络爬虫入门实战 &#8211; 实战篇</a>最先出现在<a href="https://www.dixunblog.cn">帝讯博客</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dixunblog.cn/1455.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Python 文件批量处理与自动化 &#8211; 进阶篇</title>
		<link>https://www.dixunblog.cn/1454.html</link>
					<comments>https://www.dixunblog.cn/1454.html#respond</comments>
		
		<dc:creator><![CDATA[小编]]></dc:creator>
		<pubDate>Mon, 30 Mar 2026 02:05:57 +0000</pubDate>
				<category><![CDATA[技术教程]]></category>
		<category><![CDATA[编程代码]]></category>
		<category><![CDATA[Python 教程]]></category>
		<category><![CDATA[python-file]]></category>
		<category><![CDATA[代码教程]]></category>
		<guid isPermaLink="false">https://www.dixunblog.cn/1454.html</guid>

					<description><![CDATA[<p>欢迎来到今天的 Python 实战教程！今天我们来深入学习 Python 文件批量处理与自动化。这是每个 Python 开发者都必须掌握的核心技能。无论是处理日志文件、批量重命名、数据清洗。还是自动化办公。都离不开文件操作。</p>
<p>一、文件读写基础</p>
<p>1.1 打开文件的正确方式<br />
Python 使用 open() 函数打开文...</p>
<p><a href="https://www.dixunblog.cn/1454.html">Python 文件批量处理与自动化 &#8211; 进阶篇</a>最先出现在<a href="https://www.dixunblog.cn">帝讯博客</a>。</p>
]]></description>
										<content:encoded><![CDATA[<p>欢迎来到今天的 Python 实战教程！今天我们来深入学习 Python 文件批量处理与自动化。这是每个 Python 开发者都必须掌握的核心技能。无论是处理日志文件、批量重命名、数据清洗。还是自动化办公。都离不开文件操作。</p>
<h2><img decoding="async" class="alignnone size-full wp-image-1442" src="http://cdn.hyclive.cn/dixunblog/2026/03/生成Python办公插图.png" alt="" width="2730" height="1535" /></h2>
<h2>一、文件读写基础</h2>
<h3>1.1 打开文件的正确方式</h3>
<p>Python 使用 <code>open()</code> 函数打开文件。推荐使用 <code>with</code> 语句。它会自动关闭文件：</p>
<pre><code class="language-python"># 推荐方式 - with 语句自动关闭文件
with open('data.txt', 'r', encoding='utf-8') as f:
    content = f.read()
# 文件自动关闭。无需手动 f.close()

# 不推荐 - 需要手动关闭
f = open('data.txt', 'r', encoding='utf-8')
content = f.read()
f.close()  # 忘记关闭会导致资源泄漏</code></pre>
<h3>1.2 文件打开模式详解</h3>
<table class="wp-block-table">
<thead>
<tr>
<th>模式</th>
<th>说明</th>
<th>文件不存在</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>'r'</code></td>
<td>只读（默认）</td>
<td>报错</td>
</tr>
<tr>
<td><code>'w'</code></td>
<td>写入（清空原文件）</td>
<td>创建新文件</td>
</tr>
<tr>
<td><code>'a'</code></td>
<td>追加（在末尾添加）</td>
<td>创建新文件</td>
</tr>
<tr>
<td><code>'x'</code></td>
<td>独占创建</td>
<td>报错（如果已存在）</td>
</tr>
<tr>
<td><code>'b'</code></td>
<td>二进制模式</td>
<td>配合其他模式使用</td>
</tr>
<tr>
<td><code>'t'</code></td>
<td>文本模式（默认）</td>
<td>配合其他模式使用</td>
</tr>
</tbody>
</table>
<h3>1.3 读取文件的三种方法</h3>
<pre><code class="language-python"># 方法 1：read() - 读取整个文件
with open('data.txt', 'r', encoding='utf-8') as f:
    content = f.read()  # 返回字符串
    print(f"文件大小：{len(content)} 字节")

# 方法 2：readline() - 逐行读取
with open('data.txt', 'r', encoding='utf-8') as f:
    line1 = f.readline()  # 读取第一行
    line2 = f.readline()  # 读取第二行
    print(f"第一行：{line1.strip()}")

# 方法 3：readlines() - 读取所有行到列表
with open('data.txt', 'r', encoding='utf-8') as f:
    lines = f.readlines()  # 返回字符串列表
    print(f"共 {len(lines)} 行")
    for i, line in enumerate(lines, 1):
        print(f"第{i}行：{line.strip()}")

# 推荐：直接迭代文件对象（最省内存）
with open('data.txt', 'r', encoding='utf-8') as f:
    for line_num, line in enumerate(f, 1):
        print(f"第{line_num}行：{line.strip()}")</code></pre>
<h3>1.4 写入文件的多种方式</h3>
<pre><code class="language-python"># 写入模式（会清空原文件）
with open('output.txt', 'w', encoding='utf-8') as f:
    f.write("第一行内容\n")
    f.write("第二行内容\n")
    f.write("第三行内容\n")

# 追加模式（在末尾添加）
with open('output.txt', 'a', encoding='utf-8') as f:
    f.write("追加的内容\n")

# 一次性写入多行
lines = ["苹果\n", "香蕉\n", "橙子\n"]
with open('fruits.txt', 'w', encoding='utf-8') as f:
    f.writelines(lines)  # 注意：需要自己添加换行符

# 使用 print 写入文件
with open('output.txt', 'w', encoding='utf-8') as f:
    print("第一行", file=f)
    print("第二行", file=f)
    print(f"变量值：{42}", file=f)</code></pre>
<h2>二、pathlib &#8211; 现代化的路径操作</h2>
<h3>2.1 Path 对象基础</h3>
<pre><code class="language-python">from pathlib import Path

# 创建路径对象
p = Path('/home/user/documents/report.txt')

# 路径组成部分
print(p.parent)        # /home/user/documents（父目录）
print(p.name)          # report.txt（文件名）
print(p.stem)          # report（不含扩展名）
print(p.suffix)        # .txt（扩展名）
print(p.suffixes)      # ['.txt']（所有扩展名）

# 路径拼接（推荐方式）
base = Path('/home/user')
subdir = base / 'documents' / '2026'
file_path = subdir / 'report.txt'
print(file_path)  # /home/user/documents/2026/report.txt</code></pre>
<h3>2.2 路径判断与转换</h3>
<pre><code class="language-python">from pathlib import Path

p = Path('/home/user/documents')

# 路径判断
print(p.exists())        # 是否存在
print(p.is_file())       # 是否是文件
print(p.is_dir())        # 是否是目录
print(p.is_absolute())   # 是否是绝对路径

# 路径转换
print(p.absolute())      # 转为绝对路径
print(p.resolve())       # 解析符号链接后的绝对路径
print(p.relative_to('/home/user'))  # documents

# 获取当前工作目录
cwd = Path.cwd()
print(f"当前目录：{cwd}")

# 获取家目录
home = Path.home()
print(f"家目录：{home}")</code></pre>
<h2>三、批量处理文件实战</h2>
<h3>3.1 遍历目录树</h3>
<pre><code class="language-python">import os
from pathlib import Path

# 方法 1：os.walk() - 遍历目录树
for root, dirs, files in os.walk('./documents'):
    print(f"当前目录：{root}")
    print(f"子目录：{dirs}")
    print(f"文件：{files}")
    print("-" * 40)

# 方法 2：Path.glob() - 模式匹配
doc_dir = Path('./documents')

# 查找所有.txt 文件
txt_files = list(doc_dir.glob('*.txt'))
print(f"找到 {len(txt_files)} 个 txt 文件")

# 递归查找所有子目录中的.txt 文件
all_txt = list(doc_dir.rglob('*.txt'))
print(f"递归找到 {len(all_txt)} 个 txt 文件")

# 查找特定模式的文件
py_files = list(doc_dir.glob('**/*.py'))  # ** 表示递归
print(f"找到 {len(py_files)} 个 Python 文件")</code></pre>
<h3>3.2 批量重命名文件</h3>
<pre><code class="language-python">from pathlib import Path

# 批量重命名：给所有文件添加前缀
doc_dir = Path('./documents')
for file in doc_dir.glob('*.txt'):
    new_name = f"backup_{file.name}"
    file.rename(file.parent / new_name)
    print(f"重命名：{file.name} -&gt; {new_name}")

# 批量修改扩展名
for file in doc_dir.glob('*.txt'):
    new_name = file.with_suffix('.md')
    file.rename(new_name)
    print(f"修改扩展名：{file.name} -&gt; {new_name.name}")

# 按序号重命名
for i, file in enumerate(doc_dir.glob('*.md'), 1):
    new_name = file.parent / f"document_{i:03d}.md"
    file.rename(new_name)
    print(f"重命名：{file.name} -&gt; {new_name.name}")</code></pre>
<h3>3.3 批量读取与处理</h3>
<pre><code class="language-python">from pathlib import Path

# 批量读取多个文件并合并
doc_dir = Path('./documents')
all_content = []

for file in sorted(doc_dir.glob('*.txt')):
    with open(file, 'r', encoding='utf-8') as f:
        content = f.read()
        all_content.append(f"=== {file.name} ===\n{content}")

# 合并写入新文件
with open('merged.txt', 'w', encoding='utf-8') as f:
    f.write('\n'.join(all_content))

print(f"已合并 {len(all_content)} 个文件到 merged.txt")

# 批量统计文件信息
print("\n文件统计：")
for file in sorted(doc_dir.glob('*.txt')):
    stat = file.stat()
    size_kb = stat.st_size / 1024
    print(f"{file.name}: {size_kb:.2f} KB")</code></pre>
<h3>3.4 文件内容搜索与替换</h3>
<pre><code class="language-python">from pathlib import Path
import re

# 批量搜索包含特定关键词的文件
doc_dir = Path('./documents')
keyword = "Python"
matched_files = []

for file in doc_dir.glob('*.txt'):
    with open(file, 'r', encoding='utf-8') as f:
        content = f.read()
        if keyword in content:
            matched_files.append(file.name)
            count = content.count(keyword)
            print(f"{file.name}: 找到 {count} 处匹配")

print(f"\n共 {len(matched_files)} 个文件包含'{keyword}'")

# 批量替换文本
old_text = "旧版本"
new_text = "新版本"

for file in doc_dir.glob('*.txt'):
    with open(file, 'r', encoding='utf-8') as f:
        content = f.read()
    
    if old_text in content:
        new_content = content.replace(old_text, new_text)
        with open(file, 'w', encoding='utf-8') as f:
            f.write(new_content)
        print(f"已更新：{file.name}")</code></pre>
<h2>四、高级文件操作</h2>
<h3>4.1 文件复制、移动与删除</h3>
<pre><code class="language-python">from pathlib import Path
import shutil

# 复制文件
src = Path('./source.txt')
dst = Path('./backup/source_copy.txt')
dst.parent.mkdir(parents=True, exist_ok=True)  # 创建目录
shutil.copy2(src, dst)  # copy2 保留元数据
print(f"已复制：{src} -&gt; {dst}")

# 复制整个目录
shutil.copytree('./docs', './docs_backup')
print("已复制整个目录")

# 移动文件
src = Path('./old_location/file.txt')
dst = Path('./new_location/file.txt')
dst.parent.mkdir(parents=True, exist_ok=True)
shutil.move(src, dst)
print(f"已移动：{src} -&gt; {dst}")

# 删除文件
Path('./temp.txt').unlink()  # 删除单个文件
print("已删除 temp.txt")

# 删除整个目录
shutil.rmtree('./old_backup')
print("已删除目录")</code></pre>
<h3>4.2 临时文件处理</h3>
<pre><code class="language-python">import tempfile
from pathlib import Path

# 创建临时文件
with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt') as f:
    temp_path = f.name
    f.write("临时内容")
    print(f"临时文件：{temp_path}")

# 使用临时文件
with open(temp_path, 'r') as f:
    print(f"读取临时文件：{f.read()}")

# 清理临时文件
Path(temp_path).unlink()
print("已清理临时文件")

# 创建临时目录
with tempfile.TemporaryDirectory() as temp_dir:
    print(f"临时目录：{temp_dir}")
    # 在临时目录中操作
    temp_file = Path(temp_dir) / 'test.txt'
    temp_file.write_text("测试内容")
# 退出 with 后自动清理临时目录</code></pre>
<h3>4.3 文件编码处理</h3>
<pre><code class="language-python">import chardet

# 检测文件编码
def detect_encoding(file_path):
    with open(file_path, 'rb') as f:
        result = chardet.detect(f.read(10000))  # 读取前 10KB
    return result['encoding']

# 批量转换编码
from pathlib import Path

doc_dir = Path('./documents')
for file in doc_dir.glob('*.txt'):
    # 检测编码
    encoding = detect_encoding(file)
    print(f"{file.name}: 检测到编码 {encoding}")
    
    # 读取并转换为 UTF-8
    with open(file, 'r', encoding=encoding) as f:
        content = f.read()
    
    # 写回 UTF-8
    with open(file, 'w', encoding='utf-8') as f:
        f.write(content)
    print(f"已转换：{file.name}")</code></pre>
<h2>五、实战项目</h2>
<h3>5.1 日志文件分析器</h3>
<pre><code class="language-python">from pathlib import Path
from collections import Counter
import re

def analyze_log(log_path):
    '''分析日志文件'''
    log_file = Path(log_path)
    
    error_count = 0
    warning_count = 0
    error_lines = []
    
    with open(log_file, 'r', encoding='utf-8') as f:
        for line_num, line in enumerate(f, 1):
            if 'ERROR' in line:
                error_count += 1
                error_lines.append((line_num, line.strip()))
            elif 'WARNING' in line:
                warning_count += 1
    
    print(f"日志分析结果：")
    print(f"  错误数：{error_count}")
    print(f"  警告数：{warning_count}")
    print(f"\n最新错误：")
    for line_num, line in error_lines[-5:]:
        print(f"  行{line_num}: {line}")

# 使用示例
analyze_log('./app.log')</code></pre>
<h3>5.2 批量图片重命名</h3>
<pre><code class="language-python">from pathlib import Path
from datetime import datetime

def rename_photos(photo_dir, prefix="IMG"):
    '批量重命名照片'
    photo_path = Path(photo_dir)
    
    # 获取所有图片文件
    images = list(photo_path.glob('*.jpg')) + list(photo_path.glob('*.png'))
    images.sort(key=lambda p: p.stat().st_mtime)  # 按修改时间排序
    
    for i, img in enumerate(images, 1):
        # 生成新文件名
        date_str = datetime.fromtimestamp(img.stat().st_mtime).strftime('%Y%m%d')
        new_name = f"{prefix}_{date_str}_{i:04d}{img.suffix}"
        new_path = img.parent / new_name
        
        # 重命名
        img.rename(new_path)
        print(f"{img.name} -&gt; {new_name}")

# 使用示例
rename_photos('./photos', 'VACATION')</code></pre>
<h3>5.3 文件备份工具</h3>
<pre><code class="language-python">from pathlib import Path
import shutil
from datetime import datetime

def backup_files(source_dir, backup_dir, patterns=None):
    '备份指定类型的文件'
    source = Path(source_dir)
    backup = Path(backup_dir)
    
    # 创建带时间戳的备份目录
    timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
    backup_path = backup / f"backup_{timestamp}"
    backup_path.mkdir(parents=True, exist_ok=True)
    
    # 默认备份所有文件
    if patterns is None:
        patterns = ['*']
    
    # 复制文件
    copied_count = 0
    for pattern in patterns:
        for file in source.glob(pattern):
            if file.is_file():
                dest = backup_path / file.name
                shutil.copy2(file, dest)
                copied_count += 1
    
    print(f"备份完成：{copied_count} 个文件")
    print(f"备份位置：{backup_path}")
    return backup_path

# 使用示例
backup_files('./documents', './backups', ['*.txt', '*.docx', '*.pdf'])</code></pre>
<h2>六、常见错误与解决</h2>
<h3>6.1 文件不存在错误</h3>
<pre><code class="language-python">from pathlib import Path

# 错误：文件不存在会报错
# with open('not_exist.txt', 'r') as f:
#     content = f.read()  # FileNotFoundError!

# 解决：先检查是否存在
file = Path('not_exist.txt')
if file.exists():
    content = file.read_text()
else:
    print("文件不存在。创建新文件")
    file.write_text("初始内容")

# 或使用异常处理
try:
    content = file.read_text()
except FileNotFoundError:
    print("文件不存在。使用默认内容")
    content = "默认内容"</code></pre>
<h3>6.2 编码错误</h3>
<pre><code class="language-python"># 错误：编码不匹配
# with open('file.txt', 'r', encoding='ascii') as f:
#     content = f.read()  # UnicodeDecodeError!

# 解决：使用正确的编码
with open('file.txt', 'r', encoding='utf-8') as f:
    content = f.read()

# 或忽略错误
with open('file.txt', 'r', encoding='utf-8', errors='ignore') as f:
    content = f.read()

# 或替换错误字符
with open('file.txt', 'r', encoding='utf-8', errors='replace') as f:
    content = f.read()</code></pre>
<h3>6.3 权限错误</h3>
<pre><code class="language-python">from pathlib import Path

# 错误：没有写入权限
# Path('/root/protected.txt').write_text("内容")  # PermissionError!

# 解决：检查权限或选择其他目录
file = Path('./user_file.txt')
try:
    file.write_text("内容")
except PermissionError:
    print("没有权限。尝试其他目录")
    file = Path.home() / 'file.txt'
    file.write_text("内容")</code></pre>
<h2>七、最佳实践</h2>
<ol>
<li><strong>始终使用 with 语句</strong>：自动关闭文件。避免资源泄漏</li>
<li><strong>明确指定编码</strong>：始终使用 <code>encoding='utf-8'</code></li>
<li><strong>使用 pathlib</strong>：比 os.path 更现代、更易用</li>
<li><strong>大文件分块读取</strong>：避免一次性加载到内存
<pre><code class="language-python">with open('large_file.txt', 'r') as f:
    for chunk in iter(lambda: f.read(8192), ''):
        process(chunk)</code></pre>
</li>
<li><strong>先创建目录再写入</strong>：
<pre><code class="language-python">output = Path('./output/subdir/file.txt')
output.parent.mkdir(parents=True, exist_ok=True)
output.write_text("内容")</code></pre>
</li>
</ol>
<h2>八、总结与练习</h2>
<p>今天我们深入学习了 Python 文件处理的各个方面。建议：</p>
<ol>
<li><strong>掌握基础</strong>：open()、read()、write()、with 语句</li>
<li><strong>熟练使用 pathlib</strong>：现代化的路径操作</li>
<li><strong>理解编码</strong>：UTF-8 是默认选择</li>
<li><strong>多实践</strong>：通过实际项目巩固知识</li>
</ol>
<h3>课后练习</h3>
<ol>
<li>编写脚本。统计目录下所有代码文件的总行数</li>
<li>实现一个简单的文件搜索工具。支持关键词搜索</li>
<li>编写批量重命名工具。支持添加前缀、后缀、序号</li>
<li>实现日志分析器。提取错误和警告信息</li>
<li>创建自动备份脚本。定期备份重要文件</li>
</ol>
<hr />
<p><em>关注我们获取更多 Python 实战教程！下节课我们将学习 Python 网络爬虫入门。</em></p>
<p><a href="https://www.dixunblog.cn/1454.html">Python 文件批量处理与自动化 &#8211; 进阶篇</a>最先出现在<a href="https://www.dixunblog.cn">帝讯博客</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dixunblog.cn/1454.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Python 自动化办公实战：Excel 处理 &#8211; 基础篇</title>
		<link>https://www.dixunblog.cn/1453.html</link>
					<comments>https://www.dixunblog.cn/1453.html#respond</comments>
		
		<dc:creator><![CDATA[小编]]></dc:creator>
		<pubDate>Mon, 30 Mar 2026 02:05:55 +0000</pubDate>
				<category><![CDATA[技术教程]]></category>
		<category><![CDATA[编程代码]]></category>
		<category><![CDATA[Python 教程]]></category>
		<category><![CDATA[python-excel]]></category>
		<category><![CDATA[代码教程]]></category>
		<guid isPermaLink="false">https://www.dixunblog.cn/1453.html</guid>

					<description><![CDATA[<p>欢迎来到今天的 Python 实战教程！今天我们来学习 Python 自动化办公之 Excel 处理。</p>
<p>一、环境准备</p>
<p>1.1 安装库<br />
<code class="language-bash">pip install openpyxl pandas xlrd xlwt</p>
<p>1.2 库的选择</p>
<p><strong>openpy...</p>
<p><a href="https://www.dixunblog.cn/1453.html">Python 自动化办公实战：Excel 处理 &#8211; 基础篇</a>最先出现在<a href="https://www.dixunblog.cn">帝讯博客</a>。</p>
]]></description>
										<content:encoded><![CDATA[<p>欢迎来到今天的 Python 实战教程！今天我们来学习 Python 自动化办公之 Excel 处理。</p>
<h2><img decoding="async" class="alignnone size-full wp-image-1442" src="http://cdn.hyclive.cn/dixunblog/2026/03/生成Python办公插图.png" alt="" width="2730" height="1535" /></h2>
<h2>一、环境准备</h2>
<h3>1.1 安装库</h3>
<pre><code class="language-bash">pip install openpyxl pandas xlrd xlwt</code></pre>
<h3>1.2 库的选择</h3>
<ul>
<li><strong>openpyxl</strong>：读写.xlsx 文件</li>
<li><strong>pandas</strong>：数据处理和分析</li>
<li><strong>xlrd/xlwt</strong>：读写.xls 文件（旧格式）</li>
</ul>
<h2>二、读取 Excel 文件</h2>
<h3>2.1 使用 openpyxl</h3>
<pre><code class="language-python">from openpyxl import load_workbook

# 加载工作簿
wb = load_workbook('data.xlsx')

# 选择工作表
ws = wb['Sheet1']

# 读取单元格
value = ws['A1'].value

# 遍历行
for row in ws.iter_rows():
    for cell in row:
        print(cell.value)</code></pre>
<h3>2.2 使用 pandas</h3>
<pre><code class="language-python">import pandas as pd

# 读取 Excel
df = pd.read_excel('data.xlsx')

# 查看数据
print(df.head())
print(df.columns)

# 选择列
names = df['姓名']</code></pre>
<h2>三、写入 Excel 文件</h2>
<h3>3.1 创建新文件</h3>
<pre><code class="language-python">from openpyxl import Workbook

wb = Workbook()
ws = wb.active
ws.title = "数据表"

# 写入数据
ws['A1'] = "姓名"
ws['B1'] = "年龄"
ws.append(["张三", 25])
ws.append(["李四", 28])

wb.save('output.xlsx')</code></pre>
<h3>3.2 使用 pandas 写入</h3>
<pre><code class="language-python">import pandas as pd

data = {
    '姓名': ['张三', '李四'],
    '年龄': [25, 28],
    '城市': ['北京', '上海']
}

df = pd.DataFrame(data)
df.to_excel('output.xlsx', index=False)</code></pre>
<h2>四、数据处理实战</h2>
<h3>4.1 数据筛选</h3>
<pre><code class="language-python"># 筛选年龄大于 25 的记录
filtered = df[df['年龄'] &gt; 25]

# 多条件筛选
filtered = df[(df['年龄'] &gt; 25) &amp; (df['城市'] == '北京')]</code></pre>
<h3>4.2 数据统计</h3>
<pre><code class="language-python"># 平均值
avg_age = df['年龄'].mean()

# 分组统计
grouped = df.groupby('城市')['年龄'].mean()</code></pre>
<h3>4.3 数据合并</h3>
<pre><code class="language-python"># 合并两个 Excel
df1 = pd.read_excel('file1.xlsx')
df2 = pd.read_excel('file2.xlsx')

# 横向合并
merged = pd.merge(df1, df2, on='姓名')

# 纵向合并
combined = pd.concat([df1, df2])</code></pre>
<h2>五、批量处理</h2>
<h3>5.1 批量读取</h3>
<pre><code class="language-python">import os
import pandas as pd

files = [f for f in os.listdir('.') if f.endswith('.xlsx')]
all_data = []

for file in files:
    df = pd.read_excel(file)
    all_data.append(df)

combined = pd.concat(all_data)</code></pre>
<h3>5.2 批量写入</h3>
<pre><code class="language-python">departments = ['销售部', '技术部', '财务部']

for dept in departments:
    df = get_department_data(dept)
    df.to_excel(f'{dept}_报表.xlsx', index=False)</code></pre>
<h2>六、格式化与样式</h2>
<pre><code class="language-python">from openpyxl.styles import Font, PatternFill

# 设置字体
ws['A1'].font = Font(bold=True, color='FF0000')

# 设置背景色
ws['A1'].fill = PatternFill(start_color='FFFF00', fill_type='solid')

# 设置列宽
ws.column_dimensions['A'].width = 20</code></pre>
<h2>七、总结</h2>
<p>Python 处理 Excel 可以大幅提升办公效率。建议多实践。</p>
<hr />
<p><em>关注我们获取更多 Python 实战教程！</em></p>
<p><a href="https://www.dixunblog.cn/1453.html">Python 自动化办公实战：Excel 处理 &#8211; 基础篇</a>最先出现在<a href="https://www.dixunblog.cn">帝讯博客</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dixunblog.cn/1453.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Java 基础语法入门：零基础也能看懂的详细教程</title>
		<link>https://www.dixunblog.cn/1287.html</link>
					<comments>https://www.dixunblog.cn/1287.html#respond</comments>
		
		<dc:creator><![CDATA[小编]]></dc:creator>
		<pubDate>Thu, 26 Mar 2026 16:37:35 +0000</pubDate>
				<category><![CDATA[技术教程]]></category>
		<category><![CDATA[编程代码]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Windows教程]]></category>
		<category><![CDATA[代码教程]]></category>
		<guid isPermaLink="false">https://www.dixunblog.cn/1287.html</guid>

					<description><![CDATA[<p>Java 作为最流行的编程语言之一，广泛应用于企业开发、Android 应用、大数据等领域。本文从零开始讲解 Java 基础语法，包括变量、数据类型、运算符、控制流程、数组、方法、面向对象等核心概念，适合零基础初学者。</p>
<p><a href="https://www.dixunblog.cn/1287.html">Java 基础语法入门：零基础也能看懂的详细教程</a>最先出现在<a href="https://www.dixunblog.cn">帝讯博客</a>。</p>
]]></description>
										<content:encoded><![CDATA[<p>Java 作为最流行的编程语言之一，广泛应用于企业开发、Android 应用、大数据等领域。本文将带你从零开始学习 Java 基础语法。</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1325" src="http://cdn.hyclive.cn/dixunblog/2026/03/Java-基础语法入门.png" alt="" width="2730" height="1535" /></p>
<h2>一、第一个 Java 程序</h2>
<pre><code class="language-java">public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, Java!");
    }
}</code></pre>
<p>运行结果：</p>
<pre><code>Hello, Java!</code></pre>
<h3>代码解析：</h3>
<ul>
<li><code>public class</code>：定义公共类，类名必须与文件名一致</li>
<li><code>main 方法</code>：程序入口，JVM 从这里开始执行</li>
<li><code>System.out.println()</code>：控制台输出语句</li>
</ul>
<h2>二、变量与数据类型</h2>
<h3>1. 基本数据类型</h3>
<pre><code class="language-java">public class DataType {
    public static void main(String[] args) {
        // 整数类型
        int age = 25;
        long population = 7_000_000_000L;
        
        // 浮点类型
        double price = 99.99;
        float pi = 3.14f;
        
        // 字符类型
        char grade = 'A';
        
        // 布尔类型
        boolean isJavaFun = true;
        
        System.out.println("年龄：" + age);
        System.out.println("价格：" + price);
        System.out.println("等级：" + grade);
        System.out.println("有趣吗：" + isJavaFun);
    }
}</code></pre>
<h3>2. 引用数据类型</h3>
<pre><code class="language-java">String name = "张三";
String city = "北京";

System.out.println(name + "住在" + city);</code></pre>
<h2>三、运算符</h2>
<h3>1. 算术运算符</h3>
<pre><code class="language-java">int a = 10, b = 3;

System.out.println("a + b = " + (a + b));  // 13
System.out.println("a - b = " + (a - b));  // 7
System.out.println("a * b = " + (a * b));  // 30
System.out.println("a / b = " + (a / b));  // 3 (整数除法)
System.out.println("a % b = " + (a % b));  // 1 (取余)</code></pre>
<h3>2. 关系运算符</h3>
<pre><code class="language-java">int x = 5, y = 10;

System.out.println("x == y: " + (x == y));  // false
System.out.println("x != y: " + (x != y));  // true
System.out.println("x &gt; y: " + (x &gt; y));    // false
System.out.println("x &lt; y: " + (x = 5: " + (x &gt;= 5));  // true</code></pre>
<h3>3. 逻辑运算符</h3>
<pre><code class="language-java">boolean a = true, b = false;

System.out.println("a &amp;&amp; b: " + (a &amp;&amp; b));  // false (与)
System.out.println("a || b: " + (a || b));  // true (或)
System.out.println("!a: " + (!a));          // false (非)</code></pre>
<h2>四、控制流程</h2>
<h3>1. if-else 条件语句</h3>
<pre><code class="language-java">import java.util.Scanner;

public class IfExample {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入你的年龄：");
        int age = scanner.nextInt();
        
        if (age &lt; 18) {
            System.out.println("未成年");
        } else if (age &lt; 60) {
            System.out.println("成年人");
        } else {
            System.out.println("老年人");
        }
        
        scanner.close();
    }
}</code></pre>
<h3>2. switch 语句</h3>
<pre><code class="language-java">public class SwitchExample {
    public static void main(String[] args) {
        int day = 3;
        String dayName;
        
        switch (day) {
            case 1:
                dayName = "星期一";
                break;
            case 2:
                dayName = "星期二";
                break;
            case 3:
                dayName = "星期三";
                break;
            case 4:
                dayName = "星期四";
                break;
            case 5:
                dayName = "星期五";
                break;
            case 6:
            case 7:
                dayName = "周末";
                break;
            default:
                dayName = "无效的日期";
        }
        
        System.out.println("今天是：" + dayName);
    }
}</code></pre>
<h3>3. for 循环</h3>
<pre><code class="language-java">public class ForLoop {
    public static void main(String[] args) {
        // 计算 1 到 100 的和
        int sum = 0;
        for (int i = 1; i &lt;= 100; i++) {
            sum += i;
        }
        System.out.println("1 到 100 的和：" + sum);
        
        // 打印 99 乘法表
        for (int i = 1; i &lt;= 9; i++) {
            for (int j = 1; j &lt;= i; j++) {
                System.out.print(j + "×" + i + "=" + (i*j) + "  ");
            }
            System.out.println();
        }
    }
}</code></pre>
<h3>4. while 循环</h3>
<pre><code class="language-java">public class WhileLoop {
    public static void main(String[] args) {
        int count = 1;
        
        while (count &lt;= 5) {
            System.out.println("第 " + count + " 次循环");
            count++;
        }
        
        // do-while 循环
        int num = 1;
        do {
            System.out.println("至少执行一次：" + num);
            num++;
        } while (num &lt;= 3);
    }
}</code></pre>
<h2>五、数组</h2>
<pre><code class="language-java">public class ArrayExample {
    public static void main(String[] args) {
        // 声明并初始化数组
        int[] numbers = {1, 2, 3, 4, 5};
        
        // 访问数组元素
        System.out.println("第一个元素：" + numbers[0]);
        System.out.println("数组长度：" + numbers.length);
        
        // 遍历数组
        System.out.print("所有元素：");
        for (int i = 0; i &lt; numbers.length; i++) {
            System.out.print(numbers[i] + " ");
        }
        System.out.println();
        
        // 增强型 for 循环
        System.out.print("增强 for：");
        for (int num : numbers) {
            System.out.print(num + " ");
        }
        
        // 二维数组
        int[][] matrix = {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        };
        
        System.out.println("\n二维数组：");
        for (int[] row : matrix) {
            for (int val : row) {
                System.out.print(val + " ");
            }
            System.out.println();
        }
    }
}</code></pre>
<h2>六、方法（函数）</h2>
<pre><code class="language-java">public class MethodExample {
    
    // 无返回值方法
    public static void sayHello(String name) {
        System.out.println("你好，" + name + "！");
    }
    
    // 有返回值方法
    public static int add(int a, int b) {
        return a + b;
    }
    
    // 可变参数
    public static int sum(int... numbers) {
        int total = 0;
        for (int num : numbers) {
            total += num;
        }
        return total;
    }
    
    // 递归方法：计算阶乘
    public static long factorial(int n) {
        if (n == 0 || n == 1) {
            return 1;
        }
        return n * factorial(n - 1);
    }
    
    public static void main(String[] args) {
        sayHello("张三");
        
        int result = add(10, 20);
        System.out.println("10 + 20 = " + result);
        
        System.out.println("1+2+3+4+5 = " + sum(1, 2, 3, 4, 5));
        
        System.out.println("5 的阶乘 = " + factorial(5));
    }
}</code></pre>
<h2>七、面向对象基础</h2>
<h3>1. 类的定义</h3>
<pre><code class="language-java">// 定义一个学生类
class Student {
    // 成员变量
    String name;
    int age;
    String major;
    
    // 构造方法
    public Student(String name, int age, String major) {
        this.name = name;
        this.age = age;
        this.major = major;
    }
    
    // 成员方法
    public void study() {
        System.out.println(name + "正在学习" + major + "专业");
    }
    
    public void introduce() {
        System.out.println("我叫" + name + "，今年" + age + "岁");
    }
}

// 使用类
public class Main {
    public static void main(String[] args) {
        Student s1 = new Student("李四", 20, "计算机科学与技术");
        Student s2 = new Student("王五", 21, "软件工程");
        
        s1.introduce();
        s1.study();
        
        s2.introduce();
        s2.study();
    }
}</code></pre>
<h2>八、实战练习</h2>
<h3>练习 1：猜数字游戏</h3>
<pre><code class="language-java">import java.util.Random;
import java.util.Scanner;

public class GuessNumber {
    public static void main(String[] args) {
        Random random = new Random();
        int target = random.nextInt(100) + 1;
        Scanner scanner = new Scanner(System.in);
        int attempts = 0;
        
        System.out.println("=== 猜数字游戏 ===");
        System.out.println("我已经想好了一个 1-100 之间的数字");
        
        while (true) {
            System.out.print("请猜：");
            int guess = scanner.nextInt();
            attempts++;
            
            if (guess  target) {
                System.out.println("太大了！");
            } else {
                System.out.println("恭喜你猜对了！");
                System.out.println("总共猜了 " + attempts + " 次");
                break;
            }
        }
        
        scanner.close();
    }
}</code></pre>
<h2>总结</h2>
<p>本文涵盖了 Java 基础语法的核心内容：</p>
<ol>
<li>✅ 变量与数据类型</li>
<li>✅ 运算符（算术、关系、逻辑）</li>
<li>✅ 控制流程（if、switch、for、while）</li>
<li>✅ 数组（一维、二维）</li>
<li>✅ 方法定义与调用</li>
<li>✅ 面向对象基础（类与对象）</li>
</ol>
<h3>学习建议：</h3>
<ul>
<li><strong>多敲代码</strong>：把示例代码都亲手敲一遍</li>
<li><strong>多练习</strong>：完成文中的实战练习</li>
<li><strong>理解原理</strong>：不要死记硬背，理解为什么这样写</li>
<li><strong>循序渐进</strong>：基础打牢后再学习高级特性</li>
</ul>
<hr />
<p><strong>下节预告</strong>：《Java 面向对象进阶：继承、封装、多态》</p>
<p><em>如果觉得本文有帮助，欢迎收藏、转发，让更多人看到！有任何问题欢迎在评论区留言讨论。</em></p>
<p><a href="https://www.dixunblog.cn/1287.html">Java 基础语法入门：零基础也能看懂的详细教程</a>最先出现在<a href="https://www.dixunblog.cn">帝讯博客</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dixunblog.cn/1287.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>C 语言指针详解：从入门到精通的完整指南</title>
		<link>https://www.dixunblog.cn/1286.html</link>
					<comments>https://www.dixunblog.cn/1286.html#respond</comments>
		
		<dc:creator><![CDATA[小编]]></dc:creator>
		<pubDate>Thu, 26 Mar 2026 16:34:08 +0000</pubDate>
				<category><![CDATA[技术教程]]></category>
		<category><![CDATA[编程代码]]></category>
		<guid isPermaLink="false">https://www.dixunblog.cn/1286.html</guid>

					<description><![CDATA[<p>指针是 C 语言的灵魂，也是很多初学者最头疼的概念。本文通过大量实例，带你彻底理解 C 语言指针的核心用法，包括指针基础、数组与指针、函数指针、动态内存分配等。</p>
<p><a href="https://www.dixunblog.cn/1286.html">C 语言指针详解：从入门到精通的完整指南</a>最先出现在<a href="https://www.dixunblog.cn">帝讯博客</a>。</p>
]]></description>
										<content:encoded><![CDATA[<p>指针是 C 语言的灵魂，也是很多初学者最头疼的概念。本文将通过大量实例，带你彻底理解 C 语言指针的核心用法。</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1322" src="http://cdn.hyclive.cn/dixunblog/2026/03/C-语言指针主题.png" alt="" width="2730" height="1535" /></p>
<h2>什么是指针？</h2>
<p>简单来说，指针就是一个变量，它存储的是另一个变量的内存地址。想象一下，你家的地址就是一个&#8221;指针&#8221;，通过这个地址可以找到你家。</p>
<pre><code class="language-c">#include &lt;stdio.h&gt;

int main() {
    int age = 25;        // 定义一个整型变量
    int *p = &amp;age;       // p 是指针，存储 age 的地址
    
    printf("age 的值：%d\n", age);
    printf("age 的地址：%p\n", &amp;age);
    printf("指针 p 的值：%p\n", p);
    printf("指针 p 指向的值：%d\n", *p);
    
    return 0;
}</code></pre>
<p>输出结果：</p>
<pre><code>age 的值：25
age 的地址：0x7fff5fbff6ac
指针 p 的值：0x7fff5fbff6ac
指针 p 指向的值：25</code></pre>
<h2>指针的核心运算符</h2>
<h3>1. 取地址运算符 &amp;</h3>
<pre><code class="language-c">int a = 10;
int *ptr = &amp;a;  // &amp;a 获取变量 a 的地址</code></pre>
<h3>2. 解引用运算符 *</h3>
<pre><code class="language-c">int a = 10;
int *ptr = &amp;a;
printf("%d", *ptr);  // *ptr 获取 ptr 指向的值，输出 10</code></pre>
<h2>指针与数组</h2>
<p>指针和数组有着密切的关系，数组名本质上就是一个常量指针。</p>
<pre><code class="language-c">#include &lt;stdio.h&gt;

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    int *ptr = arr;  // ptr 指向数组第一个元素
    
    // 两种访问方式等价
    printf("arr[0] = %d\n", arr[0]);
    printf("*ptr = %d\n", *ptr);
    
    // 指针算术运算
    for(int i = 0; i &lt; 5; i++) {
        printf("arr[%d] = %d\n", i, *(ptr + i));
    }
    
    return 0;
}</code></pre>
<h2>指针与函数</h2>
<h3>1. 指针作为函数参数</h3>
<p>通过指针可以实现&#8221;传地址调用&#8221;，在函数内部修改外部变量的值。</p>
<pre><code class="language-c">#include &lt;stdio.h&gt;

// 交换两个数的值
void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int x = 10, y = 20;
    swap(&amp;x, &amp;y);
    printf("x = %d, y = %d\n", x, y);  // 输出：x = 20, y = 10
    return 0;
}</code></pre>
<h3>2. 返回指针的函数</h3>
<pre><code class="language-c">// 返回数组中最大值的指针
int* findMax(int arr[], int size) {
    int *maxPtr = &amp;arr[0];
    for(int i = 1; i  *maxPtr) {
            maxPtr = &amp;arr[i];
        }
    }
    return maxPtr;
}</code></pre>
<h2>二级指针</h2>
<p>指针本身也是变量，也有地址，指向指针的指针就是二级指针。</p>
<pre><code class="language-c">#include &lt;stdio.h&gt;

int main() {
    int a = 100;
    int *p1 = &amp;a;      // 一级指针
    int **p2 = &amp;p1;    // 二级指针
    
    printf("a = %d\n", a);
    printf("*p1 = %d\n", *p1);
    printf("**p2 = %d\n", **p2);
    
    return 0;
}</code></pre>
<h2>动态内存分配</h2>
<p>指针最重要的应用之一就是动态内存管理。</p>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

int main() {
    // 动态分配数组
    int n = 5;
    int *arr = (int*)malloc(n * sizeof(int));
    
    // 使用动态数组
    for(int i = 0; i &lt; n; i++) {
        arr[i] = (i + 1) * 10;
    }
    
    // 打印结果
    for(int i = 0; i &lt; n; i++) {
        printf("arr[%d] = %d\n", i, arr[i]);
    }
    
    // 释放内存
    free(arr);
    arr = NULL;  // 避免野指针
    
    return 0;
}</code></pre>
<h2>常见指针错误</h2>
<h3>1. 野指针</h3>
<pre><code class="language-c">// 错误示例
int *ptr;  // 未初始化的指针
*ptr = 10; // 危险！ptr 指向未知地址

// 正确做法
int *ptr = NULL;  // 初始化为 NULL
int a = 10;
ptr = &amp;a;         // 再赋值有效地址</code></pre>
<h3>2. 内存泄漏</h3>
<pre><code class="language-c">// 错误示例
int *ptr = (int*)malloc(sizeof(int));
*ptr = 10;
// 忘记 free(ptr)，导致内存泄漏

// 正确做法
int *ptr = (int*)malloc(sizeof(int));
*ptr = 10;
// 使用完毕后
free(ptr);
ptr = NULL;</code></pre>
<h3>3. 悬空指针</h3>
<pre><code class="language-c">// 错误示例
int *getPointer() {
    int local = 100;
    return &amp;local;  // 错误！返回局部变量地址
}

// 正确做法
int *getPointer() {
    int *ptr = (int*)malloc(sizeof(int));
    *ptr = 100;
    return ptr;  // 返回动态分配的内存
}</code></pre>
<h2>实战练习</h2>
<h3>题目 1：字符串反转</h3>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#include &lt;string.h&gt;

void reverseString(char *str) {
    char *start = str;
    char *end = str + strlen(str) - 1;
    char temp;
    
    while(start &lt; end) {
        temp = *start;
        *start = *end;
        *end = temp;
        start++;
        end--;
    }
}

int main() {
    char str[] = "Hello, World!";
    printf("原字符串：%s\n", str);
    reverseString(str);
    printf("反转后：%s\n", str);
    return 0;
}</code></pre>
<h3>题目 2：冒泡排序（指针实现）</h3>
<pre><code class="language-c">#include &lt;stdio.h&gt;

void bubbleSort(int *arr, int n) {
    for(int i = 0; i &lt; n - 1; i++) {
        for(int j = 0; j  *(arr + j + 1)) {
                int temp = *(arr + j);
                *(arr + j) = *(arr + j + 1);
                *(arr + j + 1) = temp;
            }
        }
    }
}

int main() {
    int arr[] = {64, 34, 25, 12, 22, 11, 90};
    int n = sizeof(arr) / sizeof(arr[0]);
    
    bubbleSort(arr, n);
    
    printf("排序后：");
    for(int i = 0; i &lt; n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    
    return 0;
}</code></pre>
<h2>总结</h2>
<p>指针是 C 语言的核心，掌握指针需要大量实践。以下是学习建议：</p>
<ol>
<li><strong>理解概念</strong>：指针就是地址，*和&amp;是核心运算符</li>
<li><strong>多画图</strong>：画出内存图帮助理解指针指向</li>
<li><strong>多练习</strong>：通过实际编程加深理解</li>
<li><strong>注意内存管理</strong>：malloc 和 free 配对使用</li>
<li><strong>避免常见错误</strong>：野指针、内存泄漏、悬空指针</li>
</ol>
<p>指针虽然难，但一旦掌握，你的 C 语言水平会有质的飞跃。加油！💪</p>
<hr />
<p><strong>下节预告</strong>：《数据结构基础：链表与指针的完美结合》</p>
<p><em>如果你觉得本文有帮助，欢迎收藏、转发，让更多人看到！</em></p>
<p><a href="https://www.dixunblog.cn/1286.html">C 语言指针详解：从入门到精通的完整指南</a>最先出现在<a href="https://www.dixunblog.cn">帝讯博客</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dixunblog.cn/1286.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Docker容器化部署全攻略：从零到企业级应用</title>
		<link>https://www.dixunblog.cn/1157.html</link>
					<comments>https://www.dixunblog.cn/1157.html#respond</comments>
		
		<dc:creator><![CDATA[老大]]></dc:creator>
		<pubDate>Sun, 15 Feb 2026 06:32:17 +0000</pubDate>
				<category><![CDATA[技术教程]]></category>
		<category><![CDATA[编程代码]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[容器]]></category>
		<guid isPermaLink="false">https://www.dixunblog.cn/?p=1157</guid>

					<description><![CDATA[<p><a href="https://www.dixunblog.cn/1157.html">Docker容器化部署全攻略：从零到企业级应用</a>最先出现在<a href="https://www.dixunblog.cn">帝讯博客</a>。</p>
]]></description>
										<content:encoded><![CDATA[<p

<h2><strong><b>前言</b></strong></h2>
<p>容器化技术已经成为现代应用部署的标准。随着微服务架构的普及和云原生技术的发展，Docker作为容器化的事实标准，已经深入到每个开发者的日常工作中。本文将带你从Docker基础概念开始，逐步构建企业级容器化部署方案，无论你是初学者还是有一定经验的开发者，都能从中获得实用的知识和技巧。</p>
<p>&nbsp;</p>
<h2><strong><b>第一章：Docker基础概念与安装</b></strong></h2>
<h3><strong><b>1.1 什么是Docker？</b></strong></h3>
<p>Docker是一个开源的应用容器引擎，让开发者可以打包他们的应用以及依赖包到一个可移植的容器中，然后发布到任何流行的Linux机器或Windows机器上，也可以实现虚拟化。</p>
<p>&nbsp;</p>
<p><strong><b>核心概念：</b></strong></p>
<ul>
<li><b></b><strong><b>镜像（Image）</b></strong>：只读模板，包含运行应用程序所需的所有内容</li>
<li><b></b><strong><b>容器（Container）</b></strong>：镜像的运行实例，可以启动、停止、删除</li>
<li><b></b><strong><b>仓库（Registry）</b></strong>：存储和分发镜像的地方，如Docker Hub</li>
</ul>
<p>&nbsp;</p>
<h3><strong><b>1.2 Docker安装与配置</b></strong></h3>
<h4><strong><b>Ubuntu/Debian系统</b></strong></h4>
<p><img src="https://cdn.hyclive.cn/dixunblog/2026/02/aiimg_699168a9e795f2.79572023.webp" class="attachment-full size-full" alt="Docker容器化部署全攻略：从零到企业级应用" decoding="async" loading="lazy" /></p>
<pre>         
    # 更新包索引    
    sudo apt update    
         
    # 安装必要依赖    
    sudo apt install apt-transport-https ca-certificates curl gnupg lsb-release    
         
    # 添加Docker官方GPG密钥    
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg    
         
    # 设置稳定版仓库    
    echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list &gt; /dev/null    
         
    # 安装Docker Engine    
    sudo apt update    
    sudo apt install docker-ce docker-ce-cli containerd.io    
         
    # 验证安装    
    sudo docker run hello-world    
</pre>
<p>&nbsp;</p>
<h4><strong><b>CentOS/RHEL系统</b></strong></h4>
<pre>         
    # 卸载旧版本    
    sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine    
         
    # 安装必要工具    
    sudo yum install -y yum-utils    
         
    # 添加Docker仓库    
    sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo    
         
    # 安装Docker Engine    
    sudo yum install docker-ce docker-ce-cli containerd.io    
         
    # 启动并设置开机自启    
    sudo systemctl start docker    
    sudo systemctl enable docker    
</pre>
<p>&nbsp;</p>
<h4><strong><b>Windows WSL2</b></strong></h4>
<pre>         
    # 在PowerShell中以管理员身份运行    
    wsl --install    
    # 重启计算机后，安装Docker Desktop for Windows    
    # 确保WSL2后端已启用    
</pre>
<p>&nbsp;</p>
<h3><strong><b>1.3 用户权限配置</b></strong></h3>
<p>为了避免每次使用Docker命令都需要sudo，将当前用户添加到docker组：</p>
<pre>         
    sudo usermod -aG docker $USER    
    # 重新登录或执行以下命令    
    newgrp docker    
</pre>
<p>&nbsp;</p>
<h2><strong><b>第二章：镜像构建最佳实践</b></strong></h2>
<h3><strong><b>2.1 Dockerfile编写规范</b></strong></h3>
<p><strong><b>基础Dockerfile示例：</b></strong></p>
<pre>         
    # 使用官方Node.js运行时作为基础镜像    
    FROM node:18-alpine    
         
    # 设置工作目录    
    WORKDIR /app    
         
    # 复制package.json和package-lock.json（如果存在）    
    COPY package*.json ./    
         
    # 安装依赖    
    RUN npm ci --only=production &amp;&amp; npm cache clean --force    
         
    # 复制应用源代码    
    COPY . .    
         
    # 暴露端口    
    EXPOSE 3000    
         
    # 定义环境变量    
    ENV NODE_ENV=production    
         
    # 运行应用    
    CMD ["node", "server.js"]    
</pre>
<p>&nbsp;</p>
<h3><strong><b>2.2 多阶段构建（Multi-stage Builds）</b></strong></h3>
<p>多阶段构建可以显著减小最终镜像的大小：</p>
<p>&nbsp;</p>
<pre>         
    # 构建阶段    
    FROM node:18-alpine AS builder    
    WORKDIR /app    
    COPY package*.json ./    
    RUN npm ci --only=production &amp;&amp; npm cache clean --force    
    COPY . .    
    RUN npm run build    
         
    # 运行阶段    
    FROM node:18-alpine AS runner    
    WORKDIR /app    
    COPY --from=builder /app/dist ./dist    
    COPY --from=builder /app/node_modules ./node_modules    
    COPY package*.json ./    
    EXPOSE 3000    
    CMD ["node", "dist/server.js"]    
</pre>
<p>&nbsp;</p>
<h3><strong><b>2.3 镜像优化技巧</b></strong></h3>
<p><strong><b>减少镜像层数：</b></strong></p>
<pre>         
    # 不好的做法 - 多个RUN指令    
    RUN apt-get update    
    RUN apt-get install -y curl    
    RUN apt-get install -y vim    
         
    # 好的做法 - 合并RUN指令    
    RUN apt-get update &amp;&amp;     
        apt-get install -y curl vim &amp;&amp;     
        rm -rf /var/lib/apt/lists/*    
</pre>
<p>&nbsp;</p>
<p><strong><b>使用.dockerignore文件：</b></strong></p>
<p>node_modules<br />
npm-debug.log<br />
.git<br />
.gitignore<br />
README.md<br />
.env<br />
.nyc_output<br />
coverage<br />
.nyc_output<br />
.coverage<br />
.vscode<br />
&nbsp;</p>
<h2><strong><b>第三章：Docker Compose编排多容器应用</b></strong></h2>
<h3><strong><b>3.1 Docker Compose基础</b></strong></h3>
<p>Docker Compose是一个用于定义和运行多容器Docker应用程序的工具。</p>
<p>&nbsp;</p>
<p><strong><b>docker-compose.yml示例：</b></strong></p>
<pre>         
    version: '3.8'    
         
    services:    
      web:    
        build: .    
        ports:    
          - "3000:3000"    
        environment:    
          - NODE_ENV=production    
          - DATABASE_URL=postgresql://user:password@db:5432/myapp    
        depends_on:    
          - db    
          - redis    
        volumes:    
          - ./logs:/app/logs    
         
      db:    
        image: postgres:13    
        environment:    
          POSTGRES_DB: myapp    
          POSTGRES_USER: user    
          POSTGRES_PASSWORD: password    
        volumes:    
          - postgres_data:/var/lib/postgresql/data    
        restart: unless-stopped    
         
      redis:    
        image: redis:6-alpine    
        command: redis-server --appendonly yes    
        volumes:    
          - redis_data:/data    
        restart: unless-stopped    
         
    volumes:    
      postgres_data:    
      redis_data:    
</pre>
<p>&nbsp;</p>
<h3><strong><b>3.2 环境配置管理</b></strong></h3>
<p><strong><b>多环境配置：</b></strong></p>
<pre>         
    # docker-compose.prod.yml    
    version: '3.8'    
    services:    
      web:    
        build:    
          context: .    
          dockerfile: Dockerfile.prod    
        ports:    
          - "80:3000"    
        environment:    
          - NODE_ENV=production    
        restart: unless-stopped    
         
    # docker-compose.dev.yml      
    version: '3.8'    
    services:    
      web:    
        build:    
          context: .    
          dockerfile: Dockerfile.dev    
        ports:    
          - "3000:3000"    
        environment:    
          - NODE_ENV=development    
        volumes:    
          - .:/app    
          - /app/node_modules    
</pre>
<p>&nbsp;</p>
<p><strong><b>使用命令：</b></strong></p>
<pre>         
    # 开发环境    
    docker-compose -f docker-compose.yml -f docker-compose.dev.yml up    
         
    # 生产环境    
    docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d    
</pre>
<p>&nbsp;</p>
<h2><strong><b>第四章：网络配置与数据持久化</b></strong></h2>
<h3><strong><b>4.1 Docker网络模式</b></strong></h3>
<p><strong><b>四种网络模式：</b></strong></p>
<ol>
<li><strong><b>bridge</b></strong>（默认）：容器间通过虚拟网桥通信</li>
<li><strong><b>host</b></strong>：容器直接使用主机网络</li>
<li><strong><b>none</b></strong>：容器无网络</li>
<li><strong><b>overlay</b></strong>：跨主机容器通信</li>
</ol>
<p>&nbsp;</p>
<p><strong><b>自定义网络：</b></strong></p>
<pre>         
    # 创建自定义网络    
    docker network create --driver bridge my-network    
         
    # 运行容器时指定网络    
    docker run --network my-network --name web-app nginx    
</pre>
<p>&nbsp;</p>
<h3><strong><b>4.2 数据持久化策略</b></strong></h3>
<p><strong><b>三种数据持久化方式：</b></strong></p>
<p>&nbsp;</p>
<ol>
<li><strong><b>Volumes（推荐）</b></strong></li>
</ol>
<pre>         
    # 创建命名卷    
    docker volume create my-vol    
         
    # 挂载卷到容器    
    docker run -d --name web-app -v my-vol:/app/data nginx    
</pre>
<p>&nbsp;</p>
<ol start="2">
<li><strong><b>Bind Mounts</b></strong></li>
</ol>
<pre>         
    # 挂载主机目录    
    docker run -d --name web-app -v /host/path:/container/path nginx    
</pre>
<p>&nbsp;</p>
<ol start="3">
<li><strong><b>tmpfs Mounts</b></strong></li>
</ol>
<pre>         
    # 临时文件系统挂载（仅Linux）    
    docker run -d --name web-app --tmpfs /app/cache nginx    
</pre>
<p>&nbsp;</p>
<h2><strong><b>第五章：安全加固与资源限制</b></strong></h2>
<h3><strong><b>5.1 安全最佳实践</b></strong></h3>
<p><strong><b>使用非root用户：</b></strong></p>
<pre>         
    FROM node:18-alpine    
    RUN addgroup -g 1001 -S nodejs    
    RUN adduser -S nextjs -u 1001    
    USER nextjs    
</pre>
<p>&nbsp;</p>
<p><strong><b>扫描镜像漏洞：</b></strong></p>
<pre>         
    # 使用Docker Scout    
    docker scout quickview your-image:tag    
         
    # 使用Trivy    
    trivy image your-image:tag    
</pre>
<p>&nbsp;</p>
<p><strong><b>最小化基础镜像：</b></strong></p>
<ul>
<li>优先使用alpine版本</li>
<li>使用distroless镜像</li>
<li>定期更新基础镜像</li>
</ul>
<p>&nbsp;</p>
<h3><strong><b>5.2 资源限制</b></strong></h3>
<p><strong><b>CPU和内存限制：</b></strong></p>
<pre>         
    # docker-compose.yml    
    services:    
      web:    
        image: nginx    
        deploy:    
          resources:    
            limits:    
              cpus: '0.5'    
              memory: 512M    
            reservations:    
              cpus: '0.25'    
              memory: 256M    
</pre>
<p>&nbsp;</p>
<p><strong><b>单独容器的资源限制：</b></strong></p>
<pre>         
    docker run -d     
      --name web-app     
      --memory=512m     
      --cpus=0.5     
      nginx    
</pre>
<p>&nbsp;</p>
<h2><strong><b>第六章：CI/CD集成方案</b></strong></h2>
<h3><strong><b>6.1 GitHub Actions集成</b></strong></h3>
<p><strong><b>.github/workflows/docker-build.yml：</b></strong></p>
<pre>         
    name: Build and Push Docker Image    
         
    on:    
      push:    
        branches: [ main ]    
         
    jobs:    
      build:    
        runs-on: ubuntu-latest    
            
        steps:    
        - uses: actions/checkout@v3    
            
        - name: Set up Docker Buildx    
          uses: docker/setup-buildx-action@v2    
              
        - name: Login to Docker Hub    
          uses: docker/login-action@v2    
          with:    
            username: ${{ secrets.DOCKERHUB_USERNAME }}    
            password: ${{ secrets.DOCKERHUB_TOKEN }}    
                
        - name: Build and push    
          uses: docker/build-push-action@v4    
          with:    
            context: .    
            push: true    
            tags: your-username/your-app:latest    
</pre>
<p>&nbsp;</p>
<h3><strong><b>6.2 GitLab CI/CD集成</b></strong></h3>
<p><strong><b>.gitlab-ci.yml：</b></strong></p>
<pre>         
    stages:    
      - build    
      - test    
      - deploy    
         
    build-image:    
      stage: build    
      script:    
        - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .    
        - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA    
         
    deploy-production:    
      stage: deploy    
      script:    
        - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY    
        - docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA    
        - docker stop my-app || true    
        - docker rm my-app || true    
        - docker run -d --name my-app -p 80:3000 $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA    
      only:    
        - main    
</pre>
<p>&nbsp;</p>
<h2><strong><b>第七章：实战案例 &#8211; 完整Web应用部署</b></strong></h2>
<h3><strong><b>7.1 应用架构</b></strong></h3>
<p>我们将部署一个完整的Web应用，包含以下组件：</p>
<ul>
<li><b></b><strong><b>Nginx</b></strong>：反向代理和静态文件服务</li>
<li><b></b><strong><b>PHP-FPM</b></strong>：PHP应用服务器</li>
<li><b></b><strong><b>MySQL</b></strong>：数据库</li>
<li><b></b><strong><b>Redis</b></strong>：缓存和会话存储</li>
</ul>
<p>&nbsp;</p>
<h3><strong><b>7.2 目录结构</b></strong></h3>
<p>my-web-app/<br />
├── docker-compose.yml<br />
├── nginx/<br />
│   └── default.conf<br />
├── php/<br />
│   └── Dockerfile<br />
├── src/<br />
│   └── index.php<br />
└── .env<br />
&nbsp;</p>
<h3><strong><b>7.3 配置文件</b></strong></h3>
<p><strong><b>docker-compose.yml：</b></strong></p>
<pre>         
    version: '3.8'    
         
    services:    
      nginx:    
        image: nginx:alpine    
        ports:    
          - "80:80"    
        volumes:    
          - ./src:/var/www/html    
          - ./nginx/default.conf:/etc/nginx/conf.d/default.conf    
        depends_on:    
          - php    
        restart: unless-stopped    
         
      php:    
        build: ./php    
        volumes:    
          - ./src:/var/www/html    
        environment:    
          - DB_HOST=mysql    
          - DB_NAME=myapp    
          - DB_USER=user    
          - DB_PASS=password    
        depends_on:    
          - mysql    
          - redis    
        restart: unless-stopped    
         
      mysql:    
        image: mysql:8.0    
        environment:    
          MYSQL_DATABASE: myapp    
          MYSQL_USER: user    
          MYSQL_PASSWORD: password    
          MYSQL_ROOT_PASSWORD: rootpassword    
        volumes:    
          - mysql_data:/var/lib/mysql    
        restart: unless-stopped    
         
      redis:    
        image: redis:6-alpine    
        volumes:    
          - redis_data:/data    
        restart: unless-stopped    
         
    volumes:    
      mysql_data:    
      redis_data:    
</pre>
<p>&nbsp;</p>
<p><strong><b>nginx/default.conf：</b></strong></p>
<pre>         
    server {    
        listen 80;    
        server_name localhost;    
        root /var/www/html;    
        index index.php;    
         
        location / {    
            try_files $uri $uri/ /index.php?$query_string;    
        }    
         
        location ~ .php$ {    
            fastcgi_pass php:9000;    
            fastcgi_index index.php;    
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;    
            include fastcgi_params;    
        }    
    }    
</pre>
<p>&nbsp;</p>
<p><strong><b>php/Dockerfile：</b></strong></p>
<pre>         
    FROM php:8.1-fpm-alpine    
         
    # 安装扩展    
    RUN docker-php-ext-install mysqli pdo pdo_mysql    
         
    # 安装Redis扩展    
    RUN pecl install redis &amp;&amp; docker-php-ext-enable redis    
         
    # 清理    
    RUN rm -rf /tmp/* /var/tmp/*    
         
    WORKDIR /var/www/html    
</pre>
<p>&nbsp;</p>
<p><strong><b>src/index.php：</b></strong></p>
<pre>         
    &lt;?php    
    echo "&lt;h1&gt;欢迎使用Docker容器化部署！&lt;/h1&gt;";    
         
    // 测试数据库连接    
    try {    
        $pdo = new PDO(    
            "mysql:host=mysql;dbname=myapp",    
            "user",    
            "password"    
        );    
        echo "&lt;p&gt;✅ 数据库连接成功！&lt;/p&gt;";    
    } catch (PDOException $e) {    
        echo "&lt;p&gt;❌ 数据库连接失败: " . $e-&gt;getMessage() . "&lt;/p&gt;";    
    }    
         
    // 测试Redis连接    
    try {    
        $redis = new Redis();    
        $redis-&gt;connect('redis', 6379);    
        $redis-&gt;set('test', 'Hello Redis!');    
        echo "&lt;p&gt;✅ Redis连接成功！&lt;/p&gt;";    
        echo "&lt;p&gt;Redis测试值: " . $redis-&gt;get('test') . "&lt;/p&gt;";    
    } catch (Exception $e) {    
        echo "&lt;p&gt;❌ Redis连接失败: " . $e-&gt;getMessage() . "&lt;/p&gt;";    
    }    
    ?&gt;    
</pre>
<p>&nbsp;</p>
<h3><strong><b>7.4 部署步骤</b></strong></h3>
<pre>         
    # 1. 克隆项目    
    git clone your-repo-url    
    cd my-web-app    
         
    # 2. 构建并启动服务    
    docker-compose up -d    
         
    # 3. 验证服务状态    
    docker-compose ps    
         
    # 4. 查看日志    
    docker-compose logs -f    
         
    # 5. 访问应用    
    # 打开浏览器访问 http://localhost    
</pre>
<p>&nbsp;</p>
<h2><strong><b>第八章：监控与维护</b></strong></h2>
<h3><strong><b>8.1 日志管理</b></strong></h3>
<p><strong><b>查看容器日志：</b></strong></p>
<pre>         
    # 查看特定服务日志    
    docker-compose logs web    
         
    # 实时跟踪日志    
    docker-compose logs -f web    
         
    # 查看最近100行日志    
    docker-compose logs --tail=100 web    
</pre>
<p>&nbsp;</p>
<h3><strong><b>8.2 性能监控</b></strong></h3>
<p><strong><b>使用cAdvisor监控容器性能：</b></strong></p>
<pre>         
    # docker-compose.monitoring.yml    
    version: '3.8'    
    services:    
      cadvisor:    
        image: gcr.io/cadvisor/cadvisor:v0.47.0    
        volumes:    
          - /:/rootfs:ro    
          - /var/run:/var/run:rw    
          - /sys:/sys:ro    
          - /var/lib/docker/:/var/lib/docker:ro    
        ports:    
          - "8080:8080"    
        privileged: true    
        devices:    
          - /dev/kmsg    
</pre>
<p>&nbsp;</p>
<h3><strong><b>8.3 定期维护任务</b></strong></h3>
<p><strong><b>清理未使用的资源：</b></strong></p>
<pre>         
    # 清理停止的容器    
    docker container prune    
         
    # 清理未使用的镜像    
    docker image prune -a    
         
    # 清理未使用的卷    
    docker volume prune    
         
    # 清理未使用的网络    
    docker network prune    
         
    # 一键清理所有未使用资源    
    docker system prune -a    
</pre>
<p>&nbsp;</p>
<h2><strong><b>结语</b></strong></h2>
<p>Docker容器化部署不仅简化了应用的部署流程，还提高了环境的一致性和可移植性。通过本文的学习，你应该已经掌握了从基础概念到企业级应用部署的完整知识体系。</p>
<p>&nbsp;</p>
<p>记住，容器化不是终点，而是现代化应用开发和运维的新起点。随着Kubernetes、Service Mesh等技术的发展，容器化生态还在不断演进。保持学习，持续优化你的容器化实践！</p>
<p>&nbsp;</p>
<h2><strong><b>附录：常用Docker命令速查</b></strong></h2>
<table>
<tbody>
<tr>
<td width="366"><strong><b>命令</b></strong></td>
<td width="257"><strong><b>说明</b></strong></td>
</tr>
<tr>
<td width="366">docker ps</td>
<td width="257">列出运行中的容器</td>
</tr>
<tr>
<td width="366">docker ps -a</td>
<td width="257">列出所有容器</td>
</tr>
<tr>
<td width="366">docker images</td>
<td width="257">列出本地镜像</td>
</tr>
<tr>
<td width="366">docker build -t name:tag .</td>
<td width="257">构建镜像</td>
</tr>
<tr>
<td width="366">docker run -d &#8211;name container-name image</td>
<td width="257">运行容器</td>
</tr>
<tr>
<td width="366">docker exec -it container-name bash</td>
<td width="257">进入容器</td>
</tr>
<tr>
<td width="366">docker logs container-name</td>
<td width="257">查看容器日志</td>
</tr>
<tr>
<td width="366">docker-compose up -d</td>
<td width="257">启动所有服务</td>
</tr>
<tr>
<td width="366">docker-compose down</td>
<td width="257">停止并删除所有服务</td>
</tr>
<tr>
<td width="366">docker system df</td>
<td width="257">查看Docker磁盘使用情况</td>
</tr>
</tbody>
</table>
<p><a href="https://www.dixunblog.cn/1157.html">Docker容器化部署全攻略：从零到企业级应用</a>最先出现在<a href="https://www.dixunblog.cn">帝讯博客</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dixunblog.cn/1157.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>这些Java基础知识，诸佬们都还记得嘛(学习，复习，面试都可)</title>
		<link>https://www.dixunblog.cn/1026.html</link>
					<comments>https://www.dixunblog.cn/1026.html#respond</comments>
		
		<dc:creator><![CDATA[老大]]></dc:creator>
		<pubDate>Mon, 29 Dec 2025 08:58:21 +0000</pubDate>
				<category><![CDATA[编程代码]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[代码教程]]></category>
		<guid isPermaLink="false">https://www.dixunblog.cn/?p=1026</guid>

					<description><![CDATA[<p>JVM线程私有和共享的区域 JVM线程私有的区域有：虚拟机栈，本地方法栈，程序计数器。 虚拟机栈：主要存储方法，局部变量，运行的数据。 本地方法栈：主要存储本地方法（含有Native关键字的方法）。 程序计数器：存储程序运行位置的字节码行号指示器。 JVM线程共享的区域有：Java堆，元空间 Java堆：存储所有创建的对象，数组等。 元空间：存储虚拟机加载的字节码数据，常量，静态变量，运行时常量池等。 线程上下文切换 线程上下文切换，也就是CPU不再执行当前的线程，而去执行其他的线程。那有哪些原因会导致线程的上下文</p>
<p><a href="https://www.dixunblog.cn/1026.html">这些Java基础知识，诸佬们都还记得嘛(学习，复习，面试都可)</a>最先出现在<a href="https://www.dixunblog.cn">帝讯博客</a>。</p>
]]></description>
										<content:encoded><![CDATA[<h2 id="2j9bu">JVM线程私有和共享的区域</h2>
<p><strong>JVM线程私有的区域有：</strong><span class="mod-overview__keyword"><strong>虚拟机</strong></span><strong>栈，本地方法栈，程序计数器</strong>。</p>
<p><strong>虚拟机栈</strong>：主要存储方法，局部变量，运行的数据。 <strong>本地方法栈</strong>：主要存储本地方法（<strong>含有Native关键字的方法</strong>）。 <strong>程序计数器</strong>：存储程序运行位置的字节码行号指示器。</p>
<p><strong>JVM线程共享的区域有：</strong><strong>Java</strong><strong>堆，元空间</strong></p>
<p><span class="mod-overview__keyword"><strong>Java</strong></span><strong>堆</strong>：存储所有创建的对象，数组等。 <strong>元空间</strong>：存储虚拟机加载的字节码数据，常量，静态变量，运行时常量池等。</p>
<h2 id="dpqj">线程上下文切换</h2>
<p><strong>线程上下文切换，也就是CPU不再执行当前的线程，而去执行其他的线程</strong>。那有哪些原因会导致线程的上下文切换呢？</p>
<ol class="ol-level-0">
<li>线程的时间片用完</li>
<li>垃圾回收（会暂停当前工作的线程，先进行垃圾回收）</li>
<li>更高优先级的线程运行</li>
<li>线程主动调用了某些方法，如sleep，yeild，wait，join，synchronized，lock等</li>
</ol>
<p>当发生上下文切换时，操作系统会保存当前线程的状态，恢复另一个线程的状态，此时程序计数器会记住下一条jvm指令的执行地址，同时上文记录，<strong>程序计数器是线程私有的</strong>。</p>
<h2 id="cm987">如何判断对象是否存活</h2>
<p>判断对象是否存活有两种方法：<strong>引用计数算法和可达性分析算法</strong>。</p>
<h3 id="e1rcp">引用计数法</h3>
<p>在对象被创建的时候，会在对象头中分配一个空间，即计时器，来保存这个对象被引用的次数。如果这个对象被其他的对象引用，它的引用计数器会+1，如果删除其他对象对这个对象的引用，则它的引用计数会-1，当对象的引用计数为0时，这个对象就会被当成垃圾回收。</p>
<blockquote><p>优点： 引用计数法实现起来比较简单，判断对象是否存活的效率比较高。 缺点： 无法解决对象之间循环引用的问题，不能检测到环的出现。例如，A和B之间相互引用，此时计数器都会显示为1，此时A和B都无法进行垃圾回收。</p></blockquote>
<h3 id="6i7v0">可达性分析法</h3>
<p>Java虚拟机中的垃圾回收机制都是采用的可达性分析算法来探索存活的对象的。此种方法工作原理是会扫描java堆中的对象，沿着<strong>GC Roots对象</strong>往下寻找，看看是否能在此引用链中找到该对象，如果找不到的话，证明该对象没用了，表示该对象可以回收。</p>
<p><strong>可达性分析算法最大的优点之一就是解决了对象之间的相互循环依赖的问题，目前和引用计数法比起来没有缺点</strong>。</p>
<h2 id="3u2us">JVM中的垃圾回收算法</h2>
<p>对于新生代和老年代的对象，在JVM中会采取不同的垃圾回收算法。年轻代的对象一般都是朝生暮死的，创建之后很快就会被回收，而老年代的对象是需要长期存活的，因此用到的算法大不相同。新生代对应的收集方法为“Minor GC”，老年代对应的收集方法称为“Major GC”，而对于整个堆空间和方法区的回收被称为“Full GC”</p>
<p>&nbsp;</p>
<h3 id="15bgg">标记清除算法</h3>
<p>标记清除算法为最基础的垃圾收集算法，即为每个对象都分配一个标记为，这个标记位会记录对象的状态。标记着所要回收的对象，在标记完成后，统一回收掉所有被标记的对象，也可以标记存活的对象，清理掉未标记的对象。<strong>标记清除算法用于老年代的垃圾回收中</strong>。</p>
<blockquote><p>优点： 基于可达性分析算法，实现起来比较简单，后续的算法都是基于这种思想来实现的。 缺点： 影响最大的一点在于，<strong>标记清除算法会使内存空间碎片化</strong>，即标记并清除垃圾后，会产生很多不连续的内存空间，这将导致较大的对象因为无法找到连续的内存而提前触发一次垃圾回收。 <strong>如果大部分对象需要回收，就会进行大量的标记和清除操作，存活对象数量多时效率会降低</strong>。</p></blockquote>
<h3 id="66m77">复制算法</h3>
<p>复制算法被用于新生代的垃圾回收机制中，新生代有三部分，<strong>Eden（80%），和两个survivor区（From Survivor 和 To Survivor）</strong>。两个Survivor区为<strong>容量大小相等的两块内存</strong>，每次只使用其中的一块内存，当使用的那块内存用完后，就会将内存中还存活着的对象复制到另一块内存上，然后把使用过的那块内存空间清空。</p>
<blockquote><p>优点： 实现起来比较简单，效率也比较高，<strong>可以保证内存有连续的区域</strong>，<strong>能够解决标记清除算法导致的内存碎片问题。</strong> 缺点： 可分配的内存空间缩小了一半儿，<strong>代价比较高，内存空间浪费比较多</strong>； 存活的对象比较多的时候使用复制算法将会导致效率降低。 进行标记清除算法时，会导致应用程序挂起（停顿），即stop the world（STW）。</p></blockquote>
<p>扩展： 90%以上的对象都是朝生暮死的，所以在新生代中，每次为对象分配内存时会使用Eden区和其中的一块Survivor区，<strong>当发生垃圾回收时，JVM会将Eden和Survivor中存活的对象都复制到另一块Survivor区域内，之后清理掉Eden区和Survivor区域中的空间</strong>。综上所述，建立新对象时，新生代可用内存空间为整个儿新生代容量的90%（80%的Eden区和10%的Survivor区），如果发生了极少部分情况，即多于10%的对象存活下来了，没有被垃圾回收器回收掉，此时JVM会触发空间担保机制，即当Survivor空间不足以容纳一次Minor GC后的存活对象时，就需要依赖老年代进行分配担保。</p>
<h3 id="8611l">标记整理算法</h3>
<p>标记整理法是对标记清除算法的一个改进。第一个阶段和标记清除算法一样，都是将对象标记为存活和死亡状态，然而在第二阶段，标记清除算法只是将被标记的对象进行清除，标记整理算法会将存活的对象进行整理并且放到另一个端，然后再把所有的对象清除掉。 <strong>标记整理算法用于老年代的回收机制中</strong>。</p>
<blockquote><p>优点： 不会像垃圾清除算法那样产生不连续的内存碎片空间 不会像复制算法那样划分两个区域，提高了空间的利用率 缺点： 效率上肯定更慢一些，因为多了一步整理的操作过程。</p></blockquote>
<h2 id="dm5u5">如何判断变量是否线程安全</h2>
<p>对于成员变量和静态变量</p>
<ul class="ul-level-0">
<li>如果它们没有被共享，则它们是线程安全的；</li>
<li>如果它们被共享了，根据它们的状态是否能够改变，又会分两种情况：如果只有读操作，则它们是线程安全的；如果有读写操作，则这段代码是临界区，是需要考虑线程安全的。</li>
</ul>
<p>对于局部变量是否线程安全</p>
<ul class="ul-level-0">
<li>局部变量是线程安全的</li>
<li>但局部变量引用的对象则未必线程安全。如果该对象没有逃离方法的作用访问，它是线程安全的；如果该对象逃离方法的作用范围，则是需要考虑线程安全的。</li>
</ul>
<h2 id="5j3en">最长递增子序列</h2>
<p>给你一个整数数组 nums ，找到其中最长严格递增子序列的长度。</p>
<p>子序列 是由数组派生而来的序列，删除（或不删除）数组中的元素而不改变其余元素的顺序。例如，[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。</p>
<p>示例 1：</p>
<blockquote><p>输入：nums = [10,9,2,5,3,7,101,18] 输出：4 解释：最长递增子序列是 [2,3,7,101]，因此长度为 4 。</p>
<p>示例 2： 输入：nums = [0,1,0,3,2,3] 输出：4</p>
<p>示例 3： 输入：nums = [7,7,7,7,7,7,7] 输出：1</p></blockquote>
<p>思路：该题让求出最长的递增子序列，因此至少需要一次遍历，考虑到代码进行到每一步的状态才可以，所以动态规划法解决此题比较容易。</p>
<p>代码+详解：</p>
<div class="rno-markdown-code">
<div class="rno-markdown-code-toolbar">
<div class="rno-markdown-code-toolbar-info">
<div class="rno-markdown-code-toolbar-item"><span class="is-m-hidden">代码语言：</span>javascript</div>
</div>
<div class="rno-markdown-code-toolbar-opt">
<div class="rno-markdown-code-toolbar-opt-icon-btn is-ai-btn">
<div class="chat-ui-ai-logo css-2jdwfl"></div>
<p>AI代码解释</p>
</div>
</div>
</div>
<div class="developer-code-block">
<div class="rno-markdown-code-opt-float">
<div class="rno-markdown-code-icon-btn qa-r-editor-btn"></div>
</div>
<pre class="prism-token token line-numbers language-javascript" tabindex="0"><code class="language-javascript"><span class="token keyword">class</span> <span class="token class-name">Solution</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> int <span class="token function">lengthOfLIS</span><span class="token punctuation">(</span><span class="token parameter">int<span class="token punctuation">[</span><span class="token punctuation">]</span> nums</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span>nums<span class="token punctuation">.</span>length<span class="token operator">==</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
            <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token comment">//长度为0直接返回0</span>
        <span class="token punctuation">}</span>
        int <span class="token punctuation">[</span><span class="token punctuation">]</span> dp<span class="token operator">=</span><span class="token keyword">new</span> <span class="token class-name">int</span><span class="token punctuation">[</span>nums<span class="token punctuation">.</span>length<span class="token punctuation">]</span><span class="token punctuation">;</span>
        dp<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">;</span> <span class="token comment">//初始化数组，也可以调用库函数Arrays.fill(dp,1)，但是效率会慢些</span>
        int result<span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">;</span><span class="token comment">//初始化结果</span>
        <span class="token keyword">for</span><span class="token punctuation">(</span>int i<span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">;</span>i<span class="token operator">&lt;</span>nums<span class="token punctuation">.</span>length<span class="token punctuation">;</span>i<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
            dp<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">;</span><span class="token comment">//初始化数组</span>
            <span class="token keyword">for</span><span class="token punctuation">(</span>int j<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span>j<span class="token operator">&lt;</span>i<span class="token punctuation">;</span>j<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
                <span class="token keyword">if</span><span class="token punctuation">(</span>nums<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token operator">&lt;</span>nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
                dp<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token operator">=</span>Math<span class="token punctuation">.</span><span class="token function">max</span><span class="token punctuation">(</span>dp<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span>dp<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token operator">+</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//循环更新dp[i]的最大值</span>
                <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
            result<span class="token operator">=</span>Math<span class="token punctuation">.</span><span class="token function">max</span><span class="token punctuation">(</span>result<span class="token punctuation">,</span>dp<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">return</span> result<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
</div>
</div>
<p><a href="https://www.dixunblog.cn/1026.html">这些Java基础知识，诸佬们都还记得嘛(学习，复习，面试都可)</a>最先出现在<a href="https://www.dixunblog.cn">帝讯博客</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dixunblog.cn/1026.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>小程序的组成结构</title>
		<link>https://www.dixunblog.cn/1023.html</link>
					<comments>https://www.dixunblog.cn/1023.html#respond</comments>
		
		<dc:creator><![CDATA[老大]]></dc:creator>
		<pubDate>Mon, 29 Dec 2025 08:55:33 +0000</pubDate>
				<category><![CDATA[编程代码]]></category>
		<category><![CDATA[小程序]]></category>
		<guid isPermaLink="false">https://www.dixunblog.cn/?p=1023</guid>

					<description><![CDATA[<p>基本组成结构 （1）pages（目录）：用来存放所有小程序的页面。 （2）utils（目录）：用来存放工具性质的模板 （3）app.js:小程序项目的入口文件 （4）app.json:小程序项目的全局配置文件。 （5）app.wxss:小程序项目的全局样式文件 （6） project.config.json项目的配置文件 这是一个练习项目宿舍管理小程序，我们可以清晰地看到在文件夹miniprogram下存在的几个文件夹。 第一个文件夹images主要是存放一些小程序中所需的图片；</p>
<p><a href="https://www.dixunblog.cn/1023.html">小程序的组成结构</a>最先出现在<a href="https://www.dixunblog.cn">帝讯博客</a>。</p>
]]></description>
										<content:encoded><![CDATA[<h2 id="h8vf">基本组成结构</h2>
<p>（1）<code>pages</code>（目录）：用来存放所有小程序的页面。</p>
<p>（2）<code>utils</code>（目录）：用来存放工具性质的模板</p>
<p>（3）<code>app.js</code>:小程序项目的入口文件</p>
<p>（4）<code>app.json</code>:小程序项目的全局配置文件。</p>
<p>（5）<code>app.wxss</code>:小程序项目的全局样式文件</p>
<p>（6）<code> project.config.json</code>项目的配置文件</p>
<figure class="">
<div class="rno-markdown-img-url">
<div class="rno-markdown-img-url-inner">
<div><img loading="lazy" decoding="async" class="size-full wp-image-1024 aligncenter" title="dd379a58ab27b7ee467418623ca7a674" src="http://cdn.hyclive.cn/dixunblog/2025/12/dd379a58ab27b7ee467418623ca7a674.png" alt="dd379a58ab27b7ee467418623ca7a674" width="570" height="296" /></div>
</div>
</div>
</figure>
<p>这是一个练习项目宿舍管理小程序，我们可以清晰地看到在文件夹miniprogram下存在的几个文件夹。 第一个文件夹images主要是存放一些小程序中所需的图片；</p>
<p>[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YqBTqrBc-1664789463320)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7b41ad29e527442586288e704e3f7bba~tplv-k3u1fbpfcp-watermark.image?)]</p>
<p>pages就是存放小程序的每个页面，因为每个小程序肯定不会只有一个页面，所以pages下也存在多个页面。例如home是主页面，night是学生晚归管理界面等等。</p>
<p>[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ilBVlWH2-1664789463321)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b486a9199dff409dba11ede7c65b5d6f~tplv-k3u1fbpfcp-watermark.image?)]</p>
<h3 id="cdhd4">JSON配置</h3>
<blockquote><p><span class="mod-overview__keyword">JSON</span>是一种数据格式，在实际开发工作中，JSON总是以配置文件的形式存在。在小程序中它也是以配置文件的形式存在，通过对不同的.json配置文件进行设置，可以对小程序进行不同级别的设置。</p></blockquote>
<p>(1)小程序配置app.json</p>
<p>app.json是当前小程序的全局配置，包括了小程序的所有页面路径，窗口外观，界面表现等等。 新建一个空白的小程序，app.json默认的配置代码：</p>
<div class="rno-markdown-code">
<div class="rno-markdown-code-toolbar">
<div class="rno-markdown-code-toolbar-info">
<div class="rno-markdown-code-toolbar-item"><span class="is-m-hidden">代码语言：</span>javascript</div>
</div>
<div class="rno-markdown-code-toolbar-opt">
<div class="rno-markdown-code-toolbar-opt-icon-btn is-ai-btn">
<div class="chat-ui-ai-logo css-2jdwfl"></div>
<p>AI代码解释</p></div>
</div>
</div>
<div class="developer-code-block">
<div class="rno-markdown-code-opt-float">
<div class="rno-markdown-code-icon-btn qa-r-editor-btn"></div>
</div>
<pre class="prism-token token line-numbers language-javascript" tabindex="0"><code class="language-javascript"><span class="token punctuation">{</span>
    <span class="token string-property property">"pages"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token string">"pages/index/index"</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token string-property property">"window"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token string-property property">"backgroundTextStyle"</span><span class="token operator">:</span> <span class="token string">"light"</span><span class="token punctuation">,</span>
        <span class="token string-property property">"navigationBarBackgroundColor"</span><span class="token operator">:</span> <span class="token string">"#fff"</span><span class="token punctuation">,</span>
        <span class="token string-property property">"navigationBarTitleText"</span><span class="token operator">:</span> <span class="token string">"Weixin"</span><span class="token punctuation">,</span>
        <span class="token string-property property">"navigationBarTextStyle"</span><span class="token operator">:</span> <span class="token string">"black"</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token string-property property">"style"</span><span class="token operator">:</span> <span class="token string">"v2"</span><span class="token punctuation">,</span>
    <span class="token string-property property">"sitemapLocation"</span><span class="token operator">:</span> <span class="token string">"sitemap.json"</span>
<span class="token punctuation">}</span></code></pre>
</div>
</div>
<p>其中pages是用来记录所有页面的路径，window记录全局页面的背景和文字颜色；style定义了组件的样式版本；sitemapLocation用来指明sitemap.json的位置</p>
<p>（2） 工具配置project.config.json</p>
<p>小程序的每个项目根目录下都会生成一个工具配置文件，主要目的就是方便开发者根据自己的兴趣爱好进行一些个性化配置，比如界面颜色、编译配置等方面。你在开发者工具中进行的任何配置都是会写入到这个文件的。</p>
<p>（3）页面配置page.json</p>
<p>小程序中的每一个页面，可以使用.json文件来对本页面的窗口外观进行配置，页面中的配置项会覆盖app.json的window中相同的配置项。</p>
<h3 id="688go">WXML 模板</h3>
<p>其实小程序的开发和网页开发很类似，学过前端的小伙伴都知道网页是通过html+<span class="mod-overview__keyword">css</span>+js进行开发的。而在小程序中wxml充当的就是网页中html的角色。</p>
<div class="rno-markdown-code">
<div class="rno-markdown-code-toolbar">
<div class="rno-markdown-code-toolbar-info">
<div class="rno-markdown-code-toolbar-item"><span class="is-m-hidden">代码语言：</span>javascript</div>
</div>
<div class="rno-markdown-code-toolbar-opt">
<div class="rno-markdown-code-toolbar-opt-icon-btn is-ai-btn">
<div class="chat-ui-ai-logo css-2jdwfl"></div>
<p>AI代码解释</p></div>
</div>
</div>
<div class="developer-code-block">
<div class="rno-markdown-code-opt-float">
<div class="rno-markdown-code-icon-btn qa-r-editor-btn"></div>
</div>
<pre class="prism-token token line-numbers language-javascript" tabindex="0"><code class="language-javascript"><span class="token operator">&lt;</span>view <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"container"</span><span class="token operator">&gt;</span>
  <span class="token operator">&lt;</span>view <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"userinfo"</span><span class="token operator">&gt;</span>
    <span class="token operator">&lt;</span>button wx<span class="token operator">:</span><span class="token keyword">if</span><span class="token operator">=</span><span class="token string">"{{!hasUserInfo &amp;&amp; canIUse}}"</span><span class="token operator">&gt;</span> 获取头像昵称 <span class="token operator">&lt;</span><span class="token operator">/</span>button<span class="token operator">&gt;</span>
    <span class="token operator">&lt;</span>block wx<span class="token operator">:</span><span class="token keyword">else</span><span class="token operator">&gt;</span>
      <span class="token operator">&lt;</span>image src<span class="token operator">=</span><span class="token string">"{{userInfo.avatarUrl}}"</span> background<span class="token operator">-</span>size<span class="token operator">=</span><span class="token string">"cover"</span><span class="token operator">&gt;</span><span class="token operator">&lt;</span><span class="token operator">/</span>image<span class="token operator">&gt;</span>
      <span class="token operator">&lt;</span>text <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"userinfo-nickname"</span><span class="token operator">&gt;</span><span class="token punctuation">{</span><span class="token punctuation">{</span>userInfo<span class="token punctuation">.</span>nickName<span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span>text<span class="token operator">&gt;</span>
    <span class="token operator">&lt;</span><span class="token operator">/</span>block<span class="token operator">&gt;</span>
  <span class="token operator">&lt;</span><span class="token operator">/</span>view<span class="token operator">&gt;</span>
  <span class="token operator">&lt;</span>view <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"usermotto"</span><span class="token operator">&gt;</span>
    <span class="token operator">&lt;</span>text <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"user-motto"</span><span class="token operator">&gt;</span><span class="token punctuation">{</span><span class="token punctuation">{</span>motto<span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span>text<span class="token operator">&gt;</span>
  <span class="token operator">&lt;</span><span class="token operator">/</span>view<span class="token operator">&gt;</span>
<span class="token operator">&lt;</span><span class="token operator">/</span>view<span class="token operator">&gt;</span></code></pre>
</div>
</div>
<p>和html非常相似但也存在很多不一样的地方，</p>
<ul class="ul-level-0">
<li>标签名字不一样，小程序的标签是<code>view</code>、<code>button</code>、<code>text</code></li>
<li>多了一些 <code>wx:if</code> 这样的属性以及 {{ }} 这样的表达式</li>
<li>提供了类似于vue中的模板语法</li>
</ul>
<h3 id="2itvs">WXSS样式</h3>
<p>WXSS是一套样式语言，用于描述WXML的组件样式，相当于网页开发中的css，WXSS具有CSS的大部分特性，但也做了一些扩充和修改。</p>
<ul class="ul-level-0">
<li>新增了尺寸单位</li>
<li>提供了全局的样式和局部样式。其中app.wxss就是进行全局的样式设置。而page.wxss是进行单个页面的样式设置。</li>
<li><code>WXSS</code> 仅支持部分 <code>CSS</code> 选择器</li>
</ul>
<h3 id="798tf">JS逻辑交互</h3>
<p>一个小程序或者是界面只有静态的样式完全是不能满足人们的需求的，必须有人机交互，这一功能就是通过JS来实现的。小程序的JS文件主要分为三类：app.js是整个小程序的入口；页面的.js文件，是单独页面的入口；普通的.js文件，就是普通的功能模块文件。例如：点击一个按钮的时候，希望界面上显示“Hello”</p>
<div class="rno-markdown-code">
<div class="rno-markdown-code-toolbar">
<div class="rno-markdown-code-toolbar-info">
<div class="rno-markdown-code-toolbar-item"><span class="is-m-hidden">代码语言：</span>javascript</div>
</div>
<div class="rno-markdown-code-toolbar-opt">
<div class="rno-markdown-code-toolbar-opt-icon-btn is-ai-btn">
<div class="chat-ui-ai-logo css-2jdwfl"></div>
<p>AI代码解释</p></div>
</div>
</div>
<div class="developer-code-block">
<div class="rno-markdown-code-opt-float">
<div class="rno-markdown-code-icon-btn qa-r-editor-btn"></div>
</div>
<pre class="prism-token token line-numbers language-javascript" tabindex="0"><code class="language-javascript"><span class="token function">Page</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token function-variable function">clickMe</span><span class="token operator">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setData</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token literal-property property">msg</span><span class="token operator">:</span> <span class="token string">"Hello"</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span></code></pre>
</div>
</div>
<p>除此之外还可以通过JS调用小程序中的各种<span class="mod-overview__keyword">API</span>，利用这些API可以使用微信提供的丰富功能。比如：微信登录、获取用户信息、微信支付等等。</p>
<p><a href="https://www.dixunblog.cn/1023.html">小程序的组成结构</a>最先出现在<a href="https://www.dixunblog.cn">帝讯博客</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dixunblog.cn/1023.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>CoreNext主题1.5.2免授权 &#124; WordPress源码</title>
		<link>https://www.dixunblog.cn/965.html</link>
					<comments>https://www.dixunblog.cn/965.html#respond</comments>
		
		<dc:creator><![CDATA[老大]]></dc:creator>
		<pubDate>Sun, 28 Dec 2025 15:57:26 +0000</pubDate>
				<category><![CDATA[编程代码]]></category>
		<category><![CDATA[CoreNext主题]]></category>
		<category><![CDATA[wordpress模板]]></category>
		<category><![CDATA[主题模板]]></category>
		<guid isPermaLink="false">https://www.dixunblog.cn/?p=965</guid>

					<description><![CDATA[<p>更新日志 v1.5.2 新增 本地头像系统，开启后彻底使用本地头像 优化 SEO 功能 调整 作者边栏动态排序内容 调整 文章引用内容界面 v1.5.1 新增 头像系统 支持用户自行上传图片</p>
<p><a href="https://www.dixunblog.cn/965.html">CoreNext主题1.5.2免授权 | WordPress源码</a>最先出现在<a href="https://www.dixunblog.cn">帝讯博客</a>。</p>
]]></description>
										<content:encoded><![CDATA[<p>更新日志</p>
<p>v1.5.2</p>
<div>
<div>
<p>新增 本地头像系统，开启后彻底使用本地头像</p>
<p>优化 SEO 功能</p>
<p>调整 作者边栏动态排序内容</p>
<p>调整 文章引用内容界面</p>
</div>
</div>
<p>v1.5.1</p>
<div>
<p>新增 头像系统 支持用户自行上传图片 [主题设置 -&gt; 用户中心 -&gt; 允许用户上传头像]</p>
<p>修复 自动深色模式 logo 用默认</p>
<p>优化 小工具 首篇大图文章高度</p>
<p>调整 获取文章缩略图逻辑</p>
</div>
<h3 id="pk-menu-0">图片：</h3>
<p><img loading="lazy" decoding="async" class="size-full wp-image-970 aligncenter" title="17045_bface2412f4569121835cef0dd47b51a" src="http://cdn.hyclive.cn/dixunblog/2025/12/17045_bface2412f4569121835cef0dd47b51a.png" alt="17045_bface2412f4569121835cef0dd47b51a" width="1630" height="1105" /></p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-971 aligncenter" title="17045_e67ce42c8285181df0ca38834053500d" src="http://cdn.hyclive.cn/dixunblog/2025/12/17045_e67ce42c8285181df0ca38834053500d.png" alt="17045_e67ce42c8285181df0ca38834053500d" width="1629" height="1123" /></p>
<p>&nbsp;</p>
<p>下载地址：<a href="https://www.npspro.cn/wp-content/plugins/third-party-links/go.php/?id=28891&amp;url=aHR0cHM6Ly9zdXlhbjgubGFuem91Yi5jb20vaWp5N1Mxd2l6enhh" target="_blank" rel="nofollow noopener">https://suyan8.lanzoub.com/ijy7S1wizzxa</a></p>
<p><a href="https://www.dixunblog.cn/965.html">CoreNext主题1.5.2免授权 | WordPress源码</a>最先出现在<a href="https://www.dixunblog.cn">帝讯博客</a>。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.dixunblog.cn/965.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
