【PostgreSQL 05】PostgreSQL扩展开发实战:从自定义函数到插件开发的完整指南

article/2025/7/28 23:07:08

PostgreSQL扩展开发实战:从自定义函数到插件开发的完整指南

关键词: PostgreSQL扩展开发、自定义函数、插件开发、C语言扩展、SQL函数、存储过程、数据库扩展、PostgreSQL插件、PGXS、CREATE EXTENSION

摘要: 想让PostgreSQL拥有独特的超能力?本文从一个实际的业务需求出发,用通俗易懂的语言带你掌握PostgreSQL扩展开发的核心技能。从简单的SQL函数到复杂的C语言插件,从本地开发到分发部署,让你的数据库变身为专属的数据处理利器!

引言:当标准功能遇到特殊需求

想象一下这个场景:你正在开发一个金融风控系统,需要实现一个复杂的信用评分算法。这个算法涉及数十个变量的非线性计算,使用标准SQL函数实现起来既复杂又低效。每次查询都要在应用层进行计算,不仅增加了网络传输开销,还让代码变得臃肿难维护。

这时候,如果能把这个算法直接"植入"到PostgreSQL中,让数据库具备原生的信用评分能力,那该多好!

在这里插入图片描述

今天,我们就来学习如何为PostgreSQL开发扩展,让数据库拥有无限可能!

第一章:PostgreSQL扩展开发基础——搭建你的"实验室"

1.1 什么是PostgreSQL扩展?

PostgreSQL扩展就像是给数据库安装的"插件",它可以为数据库添加新的功能,包括:

  • 自定义函数:实现特定的计算逻辑
  • 新的数据类型:处理特殊格式的数据
  • 操作符:定义新的运算规则
  • 索引方法:优化特定场景的查询
  • 外部数据包装器:连接外部数据源

扩展的优势:

  • 🚀 性能:在数据库内部执行,减少数据传输
  • 🔒 安全:避免敏感数据离开数据库
  • 🎯 简化:复杂逻辑一次编写,处处调用
  • 📦 复用:可以打包分发给其他项目

1.2 开发环境准备

在开始扩展开发之前,我们需要准备开发环境:

# Ubuntu/Debian系统
sudo apt-get install postgresql-server-dev-all
sudo apt-get install build-essential# CentOS/RHEL系统
sudo yum install postgresql-devel
sudo yum install gcc gcc-c++ make# 验证安装
pg_config --version

必要的工具:

  • pg_config:获取PostgreSQL配置信息
  • PGXS:PostgreSQL扩展构建系统
  • C编译器:编译C语言扩展
  • SQL知识:编写SQL函数和控制文件

第二章:自定义函数开发——从简单到复杂

2.1 SQL函数:最简单的起点

让我们从最简单的SQL函数开始。假设我们需要一个计算BMI(身体质量指数)的函数:

-- 创建BMI计算函数
CREATE OR REPLACE FUNCTION calculate_bmi(weight_kg NUMERIC,height_m NUMERIC
) RETURNS NUMERIC AS $$
BEGIN-- 输入验证IF weight_kg <= 0 OR height_m <= 0 THENRAISE EXCEPTION 'Weight and height must be positive numbers';END IF;-- BMI = 体重(kg) / 身高(m)²RETURN ROUND(weight_kg / (height_m * height_m), 2);
END;
$$ LANGUAGE plpgsql;-- 使用示例
SELECT calculate_bmi(70, 1.75) AS bmi;  -- 结果:22.86

SQL函数的特点:

  • ✅ 开发简单,学习成本低
  • ✅ 可以使用丰富的SQL功能
  • ❌ 性能相对较低
  • ❌ 功能受SQL语言限制

2.2 PL/pgSQL函数:更强大的逻辑控制

对于更复杂的业务逻辑,我们可以使用PL/pgSQL:

-- 信用评分函数示例
CREATE OR REPLACE FUNCTION calculate_credit_score(customer_id INTEGER
) RETURNS INTEGER AS $$
DECLAREincome NUMERIC;age INTEGER;debt_ratio NUMERIC;payment_history INTEGER;base_score INTEGER := 300;final_score INTEGER;
BEGIN-- 获取客户基本信息SELECT annual_income, DATE_PART('year', AGE(birth_date)),total_debt / NULLIF(annual_income, 0),on_time_paymentsINTO income, age, debt_ratio, payment_historyFROM customers WHERE id = customer_id;-- 如果客户不存在IF NOT FOUND THENRAISE EXCEPTION 'Customer % not found', customer_id;END IF;-- 收入评分 (0-200分)CASE WHEN income >= 100000 THEN base_score := base_score + 200;WHEN income >= 50000 THEN base_score := base_score + 150;WHEN income >= 30000 THEN base_score := base_score + 100;ELSE base_score := base_score + 50;END CASE;-- 年龄评分 (0-100分)CASE WHEN age BETWEEN 25 AND 65 THEN base_score := base_score + 100;WHEN age BETWEEN 18 AND 24 OR age > 65 THEN base_score := base_score + 70;ELSE base_score := base_score + 30;END CASE;-- 负债比例评分 (0-150分)CASE WHEN debt_ratio <= 0.2 THEN base_score := base_score + 150;WHEN debt_ratio <= 0.4 THEN base_score := base_score + 100;WHEN debt_ratio <= 0.6 THEN base_score := base_score + 50;ELSE base_score := base_score + 0;END CASE;-- 还款历史评分 (0-200分)base_score := base_score + LEAST(payment_history * 2, 200);-- 确保评分在合理范围内final_score := GREATEST(300, LEAST(850, base_score));-- 记录评分历史INSERT INTO credit_score_history (customer_id, score, calculated_at)VALUES (customer_id, final_score, NOW());RETURN final_score;
END;
$$ LANGUAGE plpgsql;-- 使用示例
SELECT calculate_credit_score(12345) AS credit_score;

在这里插入图片描述

2.3 C语言函数:极致性能的选择

对于性能要求极高的场景,我们可以使用C语言编写函数。让我们创建一个高性能的字符串处理函数:

第一步:编写C代码

// string_utils.c
#include "postgres.h"
#include "fmgr.h"
#include "utils/builtins.h"
#include <string.h>
#include <ctype.h>#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif// 声明函数
PG_FUNCTION_INFO_V1(fast_upper);
PG_FUNCTION_INFO_V1(word_count);
PG_FUNCTION_INFO_V1(remove_special_chars);// 快速大写转换函数
Datum
fast_upper(PG_FUNCTION_ARGS)
{text *input = PG_GETARG_TEXT_PP(0);char *input_str = VARDATA_ANY(input);int input_len = VARSIZE_ANY_EXHDR(input);// 分配输出内存text *result = (text *) palloc(VARHDRSZ + input_len);char *result_str = VARDATA(result);// 转换为大写for (int i = 0; i < input_len; i++) {result_str[i] = toupper(input_str[i]);}SET_VARSIZE(result, VARHDRSZ + input_len);PG_RETURN_TEXT_P(result);
}// 单词计数函数
Datum
word_count(PG_FUNCTION_ARGS)
{text *input = PG_GETARG_TEXT_PP(0);char *str = text_to_cstring(input);int count = 0;bool in_word = false;for (char *p = str; *p; p++) {if (isspace(*p)) {in_word = false;} else if (!in_word) {in_word = true;count++;}}pfree(str);PG_RETURN_INT32(count);
}// 移除特殊字符函数
Datum
remove_special_chars(PG_FUNCTION_ARGS)
{text *input = PG_GETARG_TEXT_PP(0);char *input_str = text_to_cstring(input);int input_len = strlen(input_str);// 分配输出缓冲区(最大长度)char *output_str = (char *) palloc(input_len + 1);int output_idx = 0;// 过滤特殊字符for (int i = 0; i < input_len; i++) {if (isalnum(input_str[i]) || isspace(input_str[i])) {output_str[output_idx++] = input_str[i];}}output_str[output_idx] = '\0';// 创建结果text *result = cstring_to_text(output_str);pfree(input_str);pfree(output_str);PG_RETURN_TEXT_P(result);
}

第二步:创建Makefile

# Makefile
MODULE_big = string_utils
OBJS = string_utils.oEXTENSION = string_utils
DATA = string_utils--1.0.sql
PGFILEDESC = "string_utils - High-performance string utilities"PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)

第三步:创建扩展控制文件

# string_utils.control
comment = 'High-performance string utility functions'
default_version = '1.0'
module_pathname = '$libdir/string_utils'
relocatable = true

第四步:创建SQL安装脚本

-- string_utils--1.0.sql
-- 创建C函数
CREATE FUNCTION fast_upper(text) 
RETURNS text
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;CREATE FUNCTION word_count(text)
RETURNS integer
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;CREATE FUNCTION remove_special_chars(text)
RETURNS text
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;-- 创建便捷的操作符(可选)
CREATE OPERATOR ~^ (LEFTARG = text,RIGHTARG = none,PROCEDURE = fast_upper
);

第五步:编译和安装

# 编译扩展
make# 安装扩展
sudo make install# 在数据库中创建扩展
psql -d your_database -c "CREATE EXTENSION string_utils;"# 测试扩展
psql -d your_database -c "SELECT fast_upper('hello world!');"

第三章:插件开发实战——构建完整扩展

3.1 扩展设计模式

一个好的PostgreSQL扩展应该遵循以下设计模式:

1. 单一职责原则

-- 好的设计:专注于文本处理
CREATE EXTENSION text_analytics;-- 不好的设计:功能过于杂乱
CREATE EXTENSION everything_tools;

2. 版本管理

-- 支持扩展升级
CREATE EXTENSION myext VERSION '1.0';
ALTER EXTENSION myext UPDATE TO '1.1';

3. 命名空间管理

-- 使用前缀避免冲突
CREATE FUNCTION myext_calculate_score(...);
CREATE TYPE myext_result_type AS (...);

3.2 实战案例:开发一个地理位置扩展

让我们开发一个实用的地理位置处理扩展:

扩展功能规划:

  • 计算两点间距离
  • 判断点是否在多边形内
  • 地理编码和反地理编码
  • 位置聚类分析
// geo_utils.c
#include "postgres.h"
#include "fmgr.h"
#include "utils/geo_decls.h"
#include <math.h>#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif#define EARTH_RADIUS_KM 6371.0
#define PI 3.14159265359PG_FUNCTION_INFO_V1(haversine_distance);
PG_FUNCTION_INFO_V1(point_in_polygon);
PG_FUNCTION_INFO_V1(nearest_points);// 哈弗辛距离计算
Datum
haversine_distance(PG_FUNCTION_ARGS)
{float8 lat1 = PG_GETARG_FLOAT8(0);float8 lon1 = PG_GETARG_FLOAT8(1);float8 lat2 = PG_GETARG_FLOAT8(2);float8 lon2 = PG_GETARG_FLOAT8(3);// 转换为弧度float8 lat1_rad = lat1 * PI / 180.0;float8 lon1_rad = lon1 * PI / 180.0;float8 lat2_rad = lat2 * PI / 180.0;float8 lon2_rad = lon2 * PI / 180.0;// 计算差值float8 dlat = lat2_rad - lat1_rad;float8 dlon = lon2_rad - lon1_rad;// 哈弗辛公式float8 a = sin(dlat/2) * sin(dlat/2) + cos(lat1_rad) * cos(lat2_rad) * sin(dlon/2) * sin(dlon/2);float8 c = 2 * atan2(sqrt(a), sqrt(1-a));float8 distance = EARTH_RADIUS_KM * c;PG_RETURN_FLOAT8(distance);
}

对应的SQL接口:

-- geo_utils--1.0.sql-- 距离计算函数
CREATE FUNCTION haversine_distance(lat1 DOUBLE PRECISION,lon1 DOUBLE PRECISION,lat2 DOUBLE PRECISION,lon2 DOUBLE PRECISION
) RETURNS DOUBLE PRECISION
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;-- 创建便捷的视图函数
CREATE OR REPLACE FUNCTION distance_between_cities(city1 TEXT,city2 TEXT
) RETURNS DOUBLE PRECISION AS $$
DECLARElat1 DOUBLE PRECISION;lon1 DOUBLE PRECISION;lat2 DOUBLE PRECISION;lon2 DOUBLE PRECISION;
BEGIN-- 查询城市坐标SELECT latitude, longitude INTO lat1, lon1FROM cities WHERE name = city1;SELECT latitude, longitude INTO lat2, lon2FROM cities WHERE name = city2;-- 如果城市不存在IF lat1 IS NULL OR lat2 IS NULL THENRETURN NULL;END IF;-- 计算距离RETURN haversine_distance(lat1, lon1, lat2, lon2);
END;
$$ LANGUAGE plpgsql;-- 附近地点查询函数
CREATE OR REPLACE FUNCTION nearby_locations(center_lat DOUBLE PRECISION,center_lon DOUBLE PRECISION,radius_km DOUBLE PRECISION,location_table TEXT DEFAULT 'locations'
) RETURNS TABLE(id INTEGER,name TEXT,distance_km DOUBLE PRECISION
) AS $$
BEGINRETURN QUERY EXECUTE format('SELECT l.id,l.name,haversine_distance(%L, %L, l.latitude, l.longitude) as distance_kmFROM %I lWHERE haversine_distance(%L, %L, l.latitude, l.longitude) <= %LORDER BY distance_km', center_lat, center_lon, location_table, center_lat, center_lon, radius_km);
END;
$$ LANGUAGE plpgsql;

3.3 扩展测试和调试

1. 单元测试

-- 创建测试数据
CREATE TABLE test_locations (id SERIAL PRIMARY KEY,name TEXT,latitude DOUBLE PRECISION,longitude DOUBLE PRECISION
);INSERT INTO test_locations (name, latitude, longitude) VALUES('北京', 39.9042, 116.4074),('上海', 31.2304, 121.4737),('广州', 23.1291, 113.2644);-- 测试距离计算
DO $$
DECLAREdistance DOUBLE PRECISION;expected DOUBLE PRECISION := 1067.0; -- 北京到上海大约距离tolerance DOUBLE PRECISION := 50.0;
BEGINSELECT haversine_distance(39.9042, 116.4074, 31.2304, 121.4737) INTO distance;IF ABS(distance - expected) > tolerance THENRAISE EXCEPTION 'Distance test failed: expected %, got %', expected, distance;ELSERAISE NOTICE 'Distance test passed: %km', distance;END IF;
END $$;

2. 性能测试

-- 性能基准测试
DO $$
DECLAREstart_time TIMESTAMP;end_time TIMESTAMP;duration INTERVAL;
BEGINstart_time := clock_timestamp();-- 执行大量计算PERFORM haversine_distance(39.9042, 116.4074, 31.2304, 121.4737)FROM generate_series(1, 100000);end_time := clock_timestamp();duration := end_time - start_time;RAISE NOTICE 'Performance test: 100k calculations in %', duration;
END $$;

第四章:扩展分发与管理——让你的扩展走向世界

4.1 扩展打包

1. 完整的目录结构

my_extension/
├── Makefile
├── my_extension.control
├── my_extension--1.0.sql
├── my_extension--1.0--1.1.sql  # 升级脚本
├── src/
│   ├── my_extension.c
│   └── my_extension.h
├── test/
│   └── sql/
│       ├── test_basic.sql
│       └── expected/
│           └── test_basic.out
├── README.md
└── LICENSE

2. 创建升级脚本

-- my_extension--1.0--1.1.sql
-- 添加新功能
CREATE FUNCTION new_feature(text) RETURNS text
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;-- 修复现有函数
DROP FUNCTION IF EXISTS old_buggy_function(text);
CREATE FUNCTION old_buggy_function(text) RETURNS text
AS 'MODULE_PATHNAME', 'fixed_function'
LANGUAGE C IMMUTABLE STRICT;

4.2 扩展发布

1. 发布到PGXN

PGXN(PostgreSQL Extension Network)是PostgreSQL扩展的官方发布平台。

{"name": "my_extension","abstract": "A useful PostgreSQL extension","version": "1.0.0","maintainer": "Your Name <your.email@example.com>","license": "postgresql","tags": ["utility", "text processing"],"provides": {"my_extension": {"version": "1.0.0","abstract": "A useful PostgreSQL extension"}},"prereqs": {"runtime": {"requires": {"PostgreSQL": "9.6.0"}}}
}

2. 文档编写

# My Extension## 安装```bash
git clone https://github.com/yourname/my_extension.git
cd my_extension
make && sudo make install

使用

CREATE EXTENSION my_extension;
SELECT my_function('test');

API参考

my_function(text) → text

描述功能和参数…


### 4.3 扩展维护**版本兼容性检查:**```sql
-- 检查PostgreSQL版本兼容性
DO $$
BEGINIF current_setting('server_version_num')::integer < 120000 THENRAISE EXCEPTION 'This extension requires PostgreSQL 12 or later';END IF;
END $$;

自动化测试:

# .github/workflows/test.yml
name: Test Extension
on: [push, pull_request]
jobs:test:runs-on: ubuntu-lateststrategy:matrix:pg_version: [12, 13, 14, 15]steps:- uses: actions/checkout@v2- name: Setup PostgreSQLrun: |sudo apt-get install postgresql-${{ matrix.pg_version }}sudo apt-get install postgresql-server-dev-${{ matrix.pg_version }}- name: Build and testrun: |makesudo make installmake installcheck

第五章:实战案例——构建一个完整的扩展

让我们构建一个实用的JSON增强扩展,解决日常开发中的JSON处理痛点:

5.1 需求分析

目标功能:

  • JSON路径批量提取
  • JSON结构验证
  • JSON性能优化查询
  • JSON数据清洗

5.2 核心代码实现

// json_enhanced.c
#include "postgres.h"
#include "fmgr.h"
#include "utils/json.h"
#include "utils/jsonb.h"
#include "utils/builtins.h"#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endifPG_FUNCTION_INFO_V1(jsonb_extract_paths);
PG_FUNCTION_INFO_V1(jsonb_validate_schema);
PG_FUNCTION_INFO_V1(jsonb_flatten);// 批量路径提取
Datum
jsonb_extract_paths(PG_FUNCTION_ARGS)
{Jsonb *jb = PG_GETARG_JSONB_P(0);ArrayType *paths = PG_GETARG_ARRAYTYPE_P(1);// 实现批量提取逻辑// ... 详细实现代码PG_RETURN_JSONB_P(result);
}
-- json_enhanced--1.0.sql-- 批量路径提取函数
CREATE FUNCTION jsonb_extract_paths(data JSONB,paths TEXT[]
) RETURNS JSONB
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;-- JSON扁平化函数
CREATE FUNCTION jsonb_flatten(data JSONB,separator TEXT DEFAULT '.'
) RETURNS JSONB
AS $$
DECLAREresult JSONB := '{}';rec RECORD;
BEGIN-- 递归扁平化JSON结构FOR rec IN SELECT * FROM jsonb_each(data)LOOPIF jsonb_typeof(rec.value) = 'object' THEN-- 递归处理嵌套对象result := result || jsonb_flatten(rec.value, separator);ELSE-- 添加到结果中result := result || jsonb_build_object(rec.key, rec.value);END IF;END LOOP;RETURN result;
END;
$$ LANGUAGE plpgsql;-- 使用示例
SELECT jsonb_extract_paths('{"user": {"name": "John", "age": 30}, "score": 95}',ARRAY['user.name', 'score']
);

总结:扩展开发的最佳实践

通过今天的学习,我们掌握了PostgreSQL扩展开发的完整流程:

🏆 扩展开发检查清单

设计阶段:

  • ✅ 明确扩展的单一职责
  • ✅ 设计清晰的API接口
  • ✅ 考虑性能和安全性
  • ✅ 规划版本升级路径

开发阶段:

  • ✅ 选择合适的开发语言(SQL/PL/pgSQL/C)
  • ✅ 遵循PostgreSQL编码规范
  • ✅ 实现完整的错误处理
  • ✅ 编写充分的单元测试

发布阶段:

  • ✅ 完善的文档和示例
  • ✅ 多版本兼容性测试
  • ✅ 清晰的安装和使用说明
  • ✅ 开源协议和许可证

🚀 进阶学习建议

  1. 深入学习C扩展开发:掌握PostgreSQL内部API
  2. 研究知名扩展源码:PostGIS、pg_stat_statements等
  3. 参与社区贡献:向PGXN提交扩展
  4. 关注性能优化:使用profiling工具分析性能

💡 常见陷阱和解决方案

内存管理:

// 错误:忘记释放内存
char *str = palloc(100);
// ... 使用str
// 忘记pfree(str);// 正确:使用内存上下文
MemoryContext oldcontext = MemoryContextSwitchTo(some_context);
char *str = palloc(100);
// ... 使用str
MemoryContextSwitchTo(oldcontext);
// 上下文销毁时自动释放内存

类型安全:

// 错误:直接访问数据
text *input = PG_GETARG_TEXT_P(0);
char *str = VARDATA(input);  // 可能不是空字符结尾// 正确:使用安全函数
text *input = PG_GETARG_TEXT_PP(0);
char *str = text_to_cstring(input);
// ... 使用str
pfree(str);

记住,优秀的扩展不仅要功能强大,更要稳定可靠。在追求性能的同时,不要忽视代码的健壮性和可维护性。

PostgreSQL扩展开发是一门艺术,它让我们能够将数据库打造成真正符合业务需求的数据处理引擎。现在,是时候开始你的扩展开发之旅了!


参考资源

📚 官方文档

  • PostgreSQL扩展开发指南
  • C语言函数开发
  • PGXS构建系统

🛠️ 开发工具

  • PGXN Client:扩展包管理器
  • pg_prove:PostgreSQL测试框架
  • pgTAP:测试驱动开发框架
  • Valgrind:内存错误检测工具

📖 推荐阅读

  • 《PostgreSQL扩展开发实战》
  • PostgreSQL Wiki - Extension Development
  • GitHub上的优秀扩展项目

🌟 知名扩展示例

  • PostGIS:地理信息系统扩展
  • pg_stat_statements:查询统计扩展
  • uuid-ossp:UUID生成扩展
  • hstore:键值对数据类型扩展

通过学习这些优秀的扩展,你可以掌握更多的开发技巧和最佳实践。记住,实践是最好的老师,赶快开始创建你的第一个PostgreSQL扩展吧!🚀


http://www.hkcw.cn/article/lAmZgLkqJI.shtml

相关文章

家政维修平台实战11搭建服务规格

目前首页的功能我们已经搭建好了&#xff0c;当用户点击某个服务内容的时候要跳转到详情页&#xff0c;详情页需要展示服务的各类信息&#xff0c;难点是在规格切换的时候价格也要跟上有变化。 在数据源设计部分我们还没有考虑规格的问题&#xff0c;本篇我们介绍一下服务规格…

【创新实训个人博客】实现了新的前端界面

我们的项目还需要ppt展示和文案展示 实现了新的html页面 对接口进行测试示例 启动app.py和aippt部分 使用postman发送请求测试大模型api 后端命令行返回

使用lighttpd和开发板进行交互

文章目录 &#x1f9e0; 一、Lighttpd 与开发板的交互原理1. 什么是 Lighttpd&#xff1f;2. 与开发板交互的方式&#xff1f; &#x1f9fe; 二、lighttpd.conf 配置文件讲解⚠️ 注意事项&#xff1a; &#x1f4c1; 三、目录结构说明&#x1f4a1; 四、使用 C 编写 CGI 脚本…

【无标题】安富莱V5程序移植到原子探索者F4控制板带TFT LCD显示屏

安富莱V5控制板用的控制器是STM32F407IGT&#xff0c; 原子探索者用的控制器是STM32F407ZGT6. 手里有原子探索者主控板2.8寸TFT LCD屏&#xff0c;需要把安富莱程序用于原子探索者硬件来运行和显示&#xff0c;经过一番折腾&#xff0c;成功运行。 省了安富莱的硬件&#xff0c…

【从0带做】基于Springboot3+Vue3的反炸宣传网站

大家好&#xff0c;我是武哥&#xff0c;最近给大家手撸了一个基于SpringBoot3Vue3的反炸宣传网站&#xff0c;可用于毕业设计、课程设计、练手学习&#xff0c;系统全部原创&#xff0c;如有遇到网上抄袭站长的&#xff0c;欢迎联系博主~ 资料获取方式 https://www.javaxm.c…

git 如何解决分支合并冲突(VS code可视化解决+gitLab网页解决)

1、定义&#xff1a;两个分支修改了同一文件的同一行代码&#xff0c;无法自动决定如何合并代码&#xff0c;需要人工干预的情况。&#xff08;假设A提交了文件a,此时B在未拉取代码的情况下&#xff0c;直接提交是会报错的&#xff0c;此时需要拉取之后再提交才会成功&#xff…

大规模、高规格、全品类,2025郑州台球展览会,8月启幕

-同聚中原共赢未来&#xff0c;42000㎡的大型台球盛会&#xff0c;将在8月15-17日&#xff0c;在郑州中原国际会展中心启幕&#xff0c;期待台球企业、品牌和买家客户届时参与。全称&#xff1a;壹肆柒2025中国&#xff08;郑州&#xff09;国际台球产业博览会&#xff0c;同期…

学习STC51单片机23(芯片为STC89C52RCRC)

每日一言 成功的路上从不拥挤&#xff0c;因为坚持的人不多&#xff0c;你要做那个例外。 通过单片机发指令给ESP8266进行通信 通信原理(也是接线原理) 代码如下 代码解释一下&#xff0c;因为我们的指令是字符数组&#xff08;c语言没有字符串的概念&#xff09;&#xff0c;…

Roller: 抽奖系统测试的幕后剧本-测试报告

抽奖系统 - 测试报告 项目名称&#xff1a;抽奖系统 测试人员&#xff1a;LlvZi 测试时间&#xff1a;2025年5月25 - 2025年6月1 一、项目概述 该项目是一个操作简便、安全可靠的抽奖系统 。主要业务是抽奖&#xff0c;并支持管理员管理用户、奖品和抽奖活动&#xff0c;以配…

智语心桥:当AI遇上“星星的孩子”,科技如何点亮沟通之路?

目录: 引言:当科技的温度,遇见“星星的孩子”“智语心桥”:一座为孤独症儿童搭建的AI沟通之桥核心技术探秘:AI如何赋能“读心”与“对话”?个性化魔法:AI如何实现“千人千面”的精准干预?应用场景畅想:从家庭到机构,AI的全方位支持为什么是“智语心桥”?——价值、可…

c++学习之---模版

目录 一、函数模板&#xff1a; 1、基本定义格式&#xff1a; 2、模版函数的优先匹配原则&#xff1a; 二、类模板&#xff1a; 1、基本定义格式&#xff1a; 2、类模版的优先匹配原则&#xff08;有坑哦&#xff09;&#xff1a; 3、缺省值的设置&#xff1a; 4、ty…

GESP2024年3月认证C++二级( 第三部分编程题(1)乘法问题)

参考程序&#xff1a; #include <iostream> // 引入输入输出库 using namespace std; // 使用标准命名空间&#xff0c;简化代码int main() {int n; // 存储输入的数字个数cin >> n; // 读入 nlong long product 1; // 用 long long 存…

NX811NX816美光颗粒固态NX840NX845

NX811NX816美光颗粒固态NX840NX845 美光NX系列固态硬盘颗粒深度解析&#xff1a;技术、性能与市场全景透视 一、技术架构与核心特性解析 1. NX811/NX816&#xff1a;入门级市场的平衡之选 技术定位&#xff1a;基于176层TLC&#xff08;Triple-Level Cell&#xff09;3D NAN…

6、运算放大器—共模抑制比(七)

目录 1、共模抑制比&#xff08;CMRR&#xff09;的定义 2、共模误差推导 3、电阻对共模误差的影响 4、参数特性 运算放大器&#xff08;运放&#xff09;的共模抑制比&#xff08;Common-Mode Rejection Ratio, CMRR&#xff09;是衡量其抑制共模信号能力的关键参数&…

“日本7月5日末日论”疯传 漫画预言引发社会焦虑

最近,网上关于日本“末日论”的讨论引起了广泛关注。据说2025年7月5日日本将遭遇毁灭性灾难,三分之一的国土会被海水吞没,连中国游客都忙着退酒店改行程。这一说法源自30年前的一部漫画——《我所看见的未来》,作者自称梦见了未来。漫画家龙树谅曾“预言”过2011年的东日本…

卢伟冰:竞争从来不是小米面临的挑战 更重视内部优化与用户距离

小米集团发布第一季度财报后,总裁卢伟冰与投资人进行了深入交流。面对投资人关于小米未来挑战的问题,卢伟冰提出了两点看法。他指出,随着小米业务规模和组织规模的扩大,公司需要确保不偏离其价值观,并保持与用户的紧密联系。同时,小米的管理体系也需要不断升级,以匹配业…

郑钦文将第8次对阵萨巴伦卡 再战老对手

在2025年法网女单1/8决赛中,头号种子萨巴伦卡以7-5和6-3的比分击败阿尼西莫娃,顺利晋级八强。这已经是萨巴伦卡连续第三年进入法网八强,并且她在最近参加的十个大满贯赛事中都至少闯入了八强。接下来,萨巴伦卡将与中国选手郑钦文交手。两人此前已经有过七次对决,郑钦文仅在…

DeepSeek R1 重磅升级,天工超级智能体 App 上线,Claude 解锁语音新体验!| AI Weekly 5.26-6.1

&#x1f4e2;本周AI快讯 | 1分钟速览&#x1f680; 1️⃣ &#x1f9e0; DeepSeek R1-0528 重磅升级 &#xff1a;推理能力接近 o3 和 Gemini 2.5 Pro&#xff0c;AIME 2025 数学测试准确率从 70% 飙升至 87.5%&#xff0c;幻觉率降低 45-50%。 2️⃣ &#x1f50d; 阿里通义…

亚马逊FBA新规下:1个模型算准补货量,自动预警断货危机

随着亚马逊对库存管理日趋严格&#xff0c;尤其是近期FBA库存限制政策的频频调整&#xff0c;越来越多卖家开始重视智能补货的重要性。断货不仅会影响销量&#xff0c;还可能导致排名下降甚至失去黄金购物车。如何在FBA新规下精准补货、避免资金积压或断货风险&#xff1f;答案…

电工基础【3】星形(Y) 和 三角形(△) 电路切换

05 星三角形启动 (星三角启动) 1、电机星形(Y)的工作原理 2、电机三角形(△)的工作原理 3、电机星三角形启动电气原理图的讲解 4、时间继电器的讲解 -----小记----- 星三角也是很经常用&#xff0c;是很经典电路。 好&#xff0c;我们讲这个课之前的话&#xff0c;我们先了…