首页
搜索
1
招聘PHP开发工程师哪个平台更专业?
6 阅读
2
【开发】NekoIPinfo:基于GO语言的高性能IP查询服务端
3 阅读
3
湖人8连胜,赛后评分一览,两人满分,里夫斯不及格
3 阅读
4
蒋易孙天宇语言天赋藏不住了
3 阅读
5
PHP执行SQL语句方法
3 阅读
技术分享
源码分类
工具分享
采集专区
登录
搜索
私人云
累计撰写
200
篇文章
累计收到
0
条评论
首页
栏目
技术分享
源码分类
工具分享
采集专区
页面
搜索到
200
篇与
的结果
2026-03-17
(东西问)路易斯·塞科:为何说数学是跨文化的“共通语言”?
中新社上海2月1日电 题:为何说数学是跨文化的“共通语言”? ——专访多伦多大学教授、菲尔兹数学科学研究院可持续发展中心主任路易斯·塞科 作者 高志苗 当下,人工智能技术影响着全球,而在这背后,作为基础科学的数学,如同以往,同样以独特方式推动着人类社会的变革。中新社“东西问”日前在上海专访了多伦多大学教授、菲尔兹数学科学研究院可持续发展中心主任路易斯·塞科(Luis Seco),探讨人工智能时代,数学在连接东西方、推动可持续发展等方面发挥的关键作用。现将访谈实录摘要如下:中新社记者:菲尔兹数学科学研究院是国际重要的数学科学研究机构之一,为何选择在上海设立代表处?未来将聚焦哪些方面开展合作?路易斯·塞科:数学科学无处不在,尤其是在今天,人工智能已渗透到我们生活的每个角落,数学也将扮演更重要的角色,从方方面面改变我们的生活方式。 菲尔兹数学科学研究院一如其名,致力于数学研究。研究院在中国的执行机构菲数中国则基于我们在全球学术、产业、政府的三维度合作经验优势,重点围绕数学与可持续发展、气候变化等领域,引进相应的创新资源、技术项目及科学人才。通过持续深耕基础与应用研究、开展国际合作、引育海外顶尖人才,助力上海未来产业发展和新质生产力培育。 2024年9月,我们正式落地上海普陀,这也是我们在中国开展国际合作的第一站。中国是一个充满创新活力的国家,我们选择在上海设立代表处,正是因为这里拥有推动创新与转型的生态系统。目前,我们已成立两大国际数学实验室——Fefferman实验室(深耕流体力学与纳维-斯托克斯方程)与Hitchin-Ngo实验室(聚焦代数几何与数学物理),分别以我的博士导师、菲尔兹奖得主查尔斯·费夫曼(Charles Louis Fefferman)和另两位杰出的数学家奈杰尔·希钦(Nigel Hitchin)以及吴宝珠(Ngô Bảo Châu)命名。未来还将设立以水文地质学家约翰·切里(John Cherry)和图灵奖得主杰克·唐加拉(Jack Dongarra)命名的新实验室,专注于水环境与超级计算方向。我们相信,中国特别是上海,将是未来重大科技突破的发生地,我们希望成为这个未来的一部分。2024年9月,“海聚英才”全球创新创业峰会人才创业周活动——“链全球”—“Talent+”创业项目对接大会暨第五届普陀人才节开幕式现场。菲尔兹数学科学研究院中国中心在会上同步成立。高志苗 摄中新社记者:您曾提出“数据是新的石油,数学是炼油厂”,菲数中国是如何将“数据石油”提炼成驱动产业创新的“高附加值燃料”?路易斯·塞科:就像石油必须经过提炼才能成为汽油、塑料等产品一样,数据本身并无价值,唯有通过数学“提炼”,才能转化为解决实际问题的能力。通过数学,我们能从数据中解码世界,包括评估健康、优化交通、掌控金融等。生活中,智能手机导航、外卖配送等背后都是算法在调度数据,数学将原始数据转化为洞察力,这也正是人工智能技术的基础。 我们正准备在上海建立户外环境实验室,通过传感器收集土地、水、气候等数据,进行分析与建模,为水资源管理、交通优化等城市挑战提供具体的解决方案。该实验室将与我们在汉堡工业大学的实验室结成“孪生实验室”,借助上海与汉堡长达数十年的“姐妹城市”关系,将实体空间产生的数据,转化为数字空间的智慧决策,从而为环境资源管理等全球性问题找到切实的解决路径。中新社记者:全球性问题的解决需要技术突破,也需要有效的全球协作。数学能否成为一种跨国家、跨文化的“共通语言”?路易斯·塞科:20世纪的成就主要是由“个体”推动的,而21世纪的挑战必须依靠国际合作,比如清洁能源、数字化健康、智慧农业等领域。这不是一场比赛,而是一场必须携手前行的旅程。如果我们在健康领域取得突破,没有人是输家,所有人都是赢家。我认为,21世纪的成功将被重新定义,它不再是个体或单一国家的胜利,而是人类共同智慧的成果。 过去的创新很多都发生在物理空间,而今天的很多创新都发生在“认知空间”,即数据存在的空间。数学正是从这个空间中提取其价值的工具,它不仅是科学的语言,更是推动社会前进的引擎。 当下诸多前沿领域,其核心都离不开数学这把“解题之钥”,未来十年人工智能的突破也需要数学基础研究的持续供给。从电动车到未来的氢能源汽车,每一次颠覆性飞跃的背后,数学都是关键的变革催化剂,有了数学,未来将加速而来。 中国最吸引我的,是这片土地上无处不在、能将蓝图变为现实的创新渴望。我们选择在此深耕,正是因为长三角这片精心培育的“土壤”,拥有让一切创新思想茁壮成长的完整生态与养分。 现在,我们站在一个新的工业革命的面前,它不是关于机器,而是关于思想;不是关于信息,而是关于洞察。数学家没有试管只有思想和黑板,想法行不通时需要不断尝试,直到奇迹发生。在上海这片创新的热土上,菲数中国希望与中国的伙伴一起,用数学的语言,书写可持续发展的未来。路易斯认为,未来十年人工智能的突破也需要数学基础研究的持续供给。受访者供图中新社记者:对于未来想要投身数学与数据科学的年轻人,您有何建议?路易斯·塞科:我的建议分为三个方面,一是要理解我们日常享受的一切科技进步,其背后都有数学的支撑。二是不要忽视人文学科,艺术、文学、音乐等让我们成为“完整的人”。第三也是我目前最受欢迎的课程所关注的:人际沟通技巧。解决全球性挑战依赖于全球协作,而协作的基石正是跨文化、跨代际的有效沟通。(完)受访者简介:路易斯·塞科。受访者供图路易斯·塞科(Luis Seco),现任菲尔兹数学科学研究院可持续发展中心主任、多伦多大学金融工程学院院长、普林斯顿大学博士、加拿大西班牙科学协会主席、Vector人工智能研究院科学家教授、慕尼黑工业大学教授,主要研究方向是可持续发展,包括气候风险,以及将人工智能引入当今的可持续发展挑战中,为未来建设一个更美好的世界。Luis Seco教授一直致力于发展大学与工业界的关系,曾获NSERC(加拿大自然科学与工程研究委员会)创新协同奖、Caballero de la Orden del Mérito Civil(西班牙政府公民功绩勋章)等多项国际重要荣誉,并长期担任国际学术组织和科研项目评审要职,多次受邀在世界经济论坛、世界人工智能大会及《生物多样性公约》第十五次缔约方大会(COP15)等国际高端学术与政策论坛作主旨报告。其愿景是利用全球大学网络,广泛促进技术和创新相结合的领域研究,包括教育、气候风险和可持续发展。
2026年03月17日
1 阅读
0 评论
0 点赞
2026-03-17
蒋易孙天宇语言天赋藏不住了
蒋易孙天宇语言天赋藏不住了【#蒋易孙天宇语言天赋藏不住了#】“摇汞青年”的语言天赋藏不住了!2026川渝春晚,@蒋易 @孙天天天天天宇 外语大比拼!今晚2026川渝春节联欢晚会,四川卫视、重庆卫视大小屏联动开播,四川观察、第1眼同步网络直播,欢乐起来!!#2026川渝春晚直播# #2026川渝春晚#
2026年03月17日
3 阅读
0 评论
0 点赞
2026-03-17
易语言工具条减法使用技巧
易语言工具条减法操作方法如下1、 先用鼠标左键点击程序,再选择新建选项。2、 进入Windows程序窗口后,点击确认按钮完成操作。3、 依次点击扩展组件、编辑框和工具条。4、 在Windows窗口中可见编辑框与工具栏,双击工具栏即可操作。5、 在编辑框中输入内容并转换为文本格式(2-3)。海量资讯、精准解读,尽在新浪财经APP
2026年03月17日
1 阅读
0 评论
0 点赞
2026-03-17
平安融易以“AI in all”大语言模型+智能企微中台重塑金融服务体验,入选为“2026金融消保与服务创新年度案例”
3月15日,中国金融传媒正式发布“2026金融消保与服务创新优秀案例”名单。2026 年政府工作报告指出,要“加强消费者权益保护”,本次征集工作即以此为宗旨,挖掘并表彰在金融消费者权益保护与服务创新领域具备示范意义的标杆实践。平安融易(江苏)融资担保有限公司(下简称“平安融易”)凭借“AI in ALL——以大语言模型 + 智能企微中台重塑金融服务新体验”的创新实践,从近 400 个申报案例中脱颖而出,获评“金融服务便捷化优秀案例”。科技满足民众多元化需求:以AI重构金融消费者智能服务体验近年来,陆控旗下平安融易持续深化“AI in ALL”战略,将大语言模型、智能中台等前沿科技融入客户服务与消保工作的各环节,构建起覆盖智能交互、服务闭环、风险前置化解的数字化服务体系。在金融行业数字化转型进入深水区的当下,科技在消保领域的应用已从提升效率的工具,演进至重构服务逻辑与风险防线的体系层面,平安融易此次获奖的实践,正清晰勾勒出这一行业演进路径。此次入选案例中,平安融易围绕传统智能客服“复杂意图识别不准、交互机械化、服务同质化”等行业痛点,打造了基于大语言模型的新一代智能客服系统。该系统采用“LLM + 行业知识增强”融合架构,将企业专属知识库、合规文档深度注入模型推理过程,同时依托 CRM 数据中台整合 8 大维度、145 种客户标签,构建起动态精准的客户画像。在实际应用中,系统能够精准捕捉对话中的客户诉求,划分7类客户情绪,形成 2,000 余种诉求与情绪组合分流规则,输出真正有温度的拟人化应答话术。自系统升级以来,问题件均处理时效由 8 分钟/件降至 2 分钟/件,智能解决率从 76% 提升至 88%,客户满意度从 70% 跃升至 90%,以 AI 技术实现客服效能与客户体验的双重升级。在智能交互升级之外,平安融易同步以技术重构服务全流程,推出的“陆小慧”智能企微中台,围绕“降时长、简流程、优体验”核心目标,将账户查询、还款提醒、客户经理联系等高频服务事项统一归集至企业微信,实现“一键直达、一屏办理”。平台打通营销与服务系统的数据链路,客户信息在后台自动流转,真正做到让数据多跑路,让客户少等待。截至目前,“陆小慧”平台已覆盖约 86% 存量客户,关联余额规模达 1200 亿元,超 3000 名前线业务人员通过统一平台服务客户,线上咨询受理占比超 50%,已成为客户首选的贷后服务入口。平台每月可开展约 220 万人次智能还款提醒,累计助力回款约 184 亿元,以数字化手段将普惠服务触角延伸至更多长尾客群。更为关键的是,这套双引擎驱动的智能服务体系,形成了贯穿服务全周期的风险前置化解能力。依托该系统化解潜在风险比例达 94%。同时通过敏感词巡检与超时告警机制,让客户诉求与风险在早期就得到及时回应处置,将金融消费者权益保护工作落到实处。风险提示树导向,打造清朗金融网络,全方位筑牢消费者安全防线在本次3・15金融消费者权益保护教育宣传活动期间,平安融易紧扣国家金融监督管理总局“清朗金融网络 守护安心消费”活动主题,全面落实相关工作要求,在全国范围内组织各分支机构开展差异化、场景化宣教活动。以浙江分公司为例,结合政策方向,围绕快递员、外卖员等人群开展“防范金融网络乱象侵害”主题宣传;陕西分公司联动碑林区委办公室,将金融问答融入投壶互动游戏,走进社区实现寓教于乐;广东佛山分公司深度参与传承四百余年的“行通济”民俗活动,创新探索“文化 + 公益 + 金融”融合传播新模式。通过“进社区、进企业、进校园、进乡村”等“六进”行动,平安融易将消保理念渗透到基层一线,切实增强人民群众的金融获得感与安全感。值得一提的是,平安融易在消费者权益保护领域的探索远不止于此。在金融黑灰产治理方面,公司构建起“线上智能监测、线下精准打击、全维科普宣教” 的三位一体综合治理体系,2025 年累计推动工商打击 993 件,推动公安部门刑事立案 15 件,切实斩断黑灰产违法链条,守护消费者财产与信用安全;在金融知识普及方面,打造了 “线上业务旅程常态化宣教 + 线下重点场景集中化宣教” 双轮驱动模式,2025 年全年累计开展线上线下消保宣教活动 1032 场,覆盖民众超 2546 万人次,从源头提升公众金融素养与风险防范能力。这些实践与此次获奖案例相辅相成,共同构成了平安融易多维立体的消保工作格局。据了解,由中国金融传媒主导的此项案例征集活动已连续举办十余年,是业内聚焦金融服务创新、践行金融为民初心的权威标杆。2026 年度征集工作于 2 月正式启动,吸引 185 家银行、保险等金融机构提交近 400 个申报案例,覆盖金融消费者权益保护与服务创新两大领域八大类别,案例规格高、覆盖广、行业代表性突出。平安融易成功入选金融服务便捷化优秀案例,既是监管与行业对其消保工作、服务创新的权威认可,也充分彰显了其以科技重构金融服务的核心优势。纵观其布局,从前端智能交互的AI客服,到中台流程重构的企微平台,再到后端风险前置化解的监测体系,已然形成了以智能升级驱动服务体验、以科技赋能夯实消保根基的系统性实践,为行业高质量发展提供了有益参考。未来,陆控旗下平安融易将继续深化“AI in ALL”战略,持续筑牢金融消保防线,为实体经济提供更安全、高效的金融服务,持续担当金融消费者权益的守护者与行业高质量发展的护航者。
2026年03月17日
2 阅读
0 评论
0 点赞
2026-03-06
【开发】NekoIPinfo:基于GO语言的高性能IP查询服务端
高性能IP查询服务端开发日志 之前使用IP信息查询的服务也不少了,观察了不少的接口,大部分返回的数据都是json格式的数据,于是我就在想,我能不能也自己开发一个类似的查询工具玩一下?说干就干,在想清楚了软件的架构设计后,我决定开工。{lamp/}架构设计与编程语言选型 在架构设计方面,我打算进行前后端彻底解耦,前端为静态网页,后端为纯API程序。对于前端,我计划利用JS来从API获取信息并更新页面对于后端,就做最纯粹的API服务,根据查询请求响应JSON字符串在亲眼见证过PHP,Python这类动态解释型语言的效率噩梦后,我打算使用GO语言进行开发,理由很简单:GO是编译型语言,运行效率比解释型语言要高得多。GO天生就适合开发后端,抗并发能力强。相比于C语言,GO语言要更适合上手。{lamp/}构建前端 不得不说,就目前的情况,Gemini仍然是前端之神,我直接让Gemini根据我的想法设计了一套网页,还是相当不错的:<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>猫娘IP地址查询</title> <!-- 引入 Tailwind CSS 进行快速样式构建 --> <script src="https://cdn.tailwindcss.com"></script> <style> /* 自定义可爱波点纹理背景 */ body { background-color: #fff0f5; /* 极淡的粉色底色 */ background-image: radial-gradient(#ffb6c1 15%, transparent 16%), radial-gradient(#ffb6c1 15%, transparent 16%); background-size: 40px 40px; background-position: 0 0, 20px 20px; font-family: 'Nunito', 'PingFang SC', 'Microsoft YaHei', sans-serif; min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 1rem; } /* 隐藏滚动条但保留滚动功能(适配部分长列表情况) */ ::-webkit-scrollbar { width: 8px; } ::-webkit-scrollbar-track { background: #fff0f5; } ::-webkit-scrollbar-thumb { background: #ffb6c1; border-radius: 10px; } ::-webkit-scrollbar-thumb:hover { background: #ff8da1; } /* 动画效果 */ @keyframes float { 0% { transform: translateY(0px); } 50% { transform: translateY(-10px); } 100% { transform: translateY(0px); } } .float-animation { animation: float 3s ease-in-out infinite; } </style> </head> <body class="text-gray-700 w-full flex flex-col items-center"> <!-- 全局包裹容器,控制最大宽度 --> <div class="w-full max-w-2xl relative pt-8 md:pt-16 px-4 pb-12"> <!-- 装饰性猫耳 (直接悬浮在最外层) --> <div class="absolute top-4 left-4 md:left-0 text-5xl float-animation z-10" style="animation-delay: 0s;">🐱</div> <div class="absolute top-4 right-4 md:right-0 text-5xl float-animation z-10" style="animation-delay: 1.5s;">🐾</div> <!-- 头部:标题与当前IP (直接放在背景上) --> <header class="text-center mb-8 mt-2 relative z-10"> <h1 class="text-4xl md:text-5xl font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-pink-500 to-rose-400 tracking-wide drop-shadow-sm mb-4"> 猫娘IP地址查询 </h1> <p class="text-pink-600 font-medium text-lg bg-white/70 backdrop-blur-sm inline-block px-6 py-2 rounded-full border border-pink-200 shadow-sm"> 您的 IP 地址为 <span id="current-ip" class="font-bold text-pink-700 ml-1">正在获取喵...</span> </p> </header> <!-- 主体结构 --> <main> <!-- 搜索输入区域 (直接放在背景上) --> <div class="flex flex-col md:flex-row items-center justify-center mb-10 w-full group relative z-10"> <div class="relative w-full flex shadow-sm rounded-full"> <span class="absolute left-6 top-1/2 transform -translate-y-1/2 text-pink-400 text-xl">🔍</span> <input type="text" id="ip-input" placeholder="请输入要查询的 IP 地址喵~" class="w-full bg-white/90 backdrop-blur-sm border-2 border-pink-200 text-pink-700 placeholder-pink-300 px-14 py-4 rounded-full md:rounded-r-none focus:outline-none focus:border-pink-400 focus:bg-white transition-all duration-300" > </div> <button id="search-btn" class="w-full md:w-auto mt-4 md:mt-0 bg-gradient-to-r from-pink-400 to-rose-400 hover:from-pink-500 hover:to-rose-500 text-white font-bold text-lg px-8 py-4 rounded-full md:rounded-l-none md:rounded-r-full shadow-md hover:shadow-pink-300/50 transform hover:-translate-y-0.5 transition-all duration-300 whitespace-nowrap active:scale-95" > 查询喵 🐾 </button> </div> <!-- 结果列表卡片 (独立卡片,竖向列表) --> <div class="bg-white/90 backdrop-blur-sm border-4 border-pink-200 rounded-[2.5rem] p-6 md:p-10 w-full shadow-[0_10px_40px_rgba(255,182,193,0.5)]"> <div id="results-container" class="opacity-100 transition-opacity duration-500"> <ul class="flex flex-col divide-y-2 divide-pink-100/60"> <!-- 列表项 1: 国家 --> <li class="flex items-center justify-between py-4 px-2 hover:bg-pink-50 rounded-2xl transition-colors group"> <div class="flex items-center gap-4"> <span class="text-2xl group-hover:scale-110 transition-transform bg-pink-100/50 p-2 rounded-full">🌍</span> <span class="text-pink-500 font-bold tracking-wider">国家</span> </div> <span id="res-country" class="text-gray-700 font-semibold text-lg">-</span> </li> <!-- 列表项 2: 省份 --> <li class="flex items-center justify-between py-4 px-2 hover:bg-pink-50 rounded-2xl transition-colors group"> <div class="flex items-center gap-4"> <span class="text-2xl group-hover:scale-110 transition-transform bg-pink-100/50 p-2 rounded-full">🗺️</span> <span class="text-pink-500 font-bold tracking-wider">省份</span> </div> <span id="res-province" class="text-gray-700 font-semibold text-lg">-</span> </li> <!-- 列表项 3: 城市 --> <li class="flex items-center justify-between py-4 px-2 hover:bg-pink-50 rounded-2xl transition-colors group"> <div class="flex items-center gap-4"> <span class="text-2xl group-hover:scale-110 transition-transform bg-pink-100/50 p-2 rounded-full">🏙️</span> <span class="text-pink-500 font-bold tracking-wider">城市</span> </div> <span id="res-city" class="text-gray-700 font-semibold text-lg">-</span> </li> <!-- 列表项 4: ISP --> <li class="flex items-center justify-between py-4 px-2 hover:bg-pink-50 rounded-2xl transition-colors group"> <div class="flex items-center gap-4"> <span class="text-2xl group-hover:scale-110 transition-transform bg-pink-100/50 p-2 rounded-full">🏢</span> <span class="text-pink-500 font-bold tracking-wider">ISP 运营商</span> </div> <span id="res-isp" class="text-gray-700 font-semibold text-lg">-</span> </li> <!-- 列表项 5: 经纬度 --> <li class="flex items-center justify-between py-4 px-2 hover:bg-pink-50 rounded-2xl transition-colors group"> <div class="flex items-center gap-4"> <span class="text-2xl group-hover:scale-110 transition-transform bg-pink-100/50 p-2 rounded-full">🧭</span> <span class="text-pink-500 font-bold tracking-wider">经纬度</span> </div> <span id="res-latlon" class="text-gray-700 font-semibold text-lg">-</span> </li> </ul> </div> <!-- API 提示按钮 --> <div class="mt-6 flex justify-end relative z-10 border-t-2 border-dashed border-pink-100/60 pt-4"> <button id="api-info-btn" class="text-sm text-pink-400 hover:text-pink-600 font-medium flex items-center gap-1 transition-colors group"> <span class="group-hover:animate-bounce">💡</span> 开发者 API 说明 </button> </div> </div> </main> </div> <!-- API 说明弹窗 (Modal) --> <div id="api-modal" class="fixed inset-0 z-50 hidden flex items-center justify-center p-4"> <!-- 黑色半透明背景遮罩 --> <div id="api-modal-overlay" class="absolute inset-0 bg-black/30 backdrop-blur-sm opacity-0 transition-opacity duration-300"></div> <!-- 弹窗主体 --> <div id="api-modal-content" class="bg-white border-4 border-pink-200 rounded-[2rem] p-6 md:p-8 max-w-lg w-full shadow-2xl relative z-10 opacity-0 scale-95 transition-all duration-300"> <div class="flex justify-between items-center mb-6"> <h2 class="text-2xl font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-pink-400 to-rose-400"> 🛠️ API 调用说明 </h2> <button id="close-modal-top" class="text-pink-300 hover:text-pink-500 text-3xl transition-colors leading-none">×</button> </div> <div class="text-gray-600 text-sm space-y-4"> <p>您可以通过发送 <code class="bg-pink-50 text-pink-600 px-1 py-0.5 rounded font-bold">GET</code> 请求到我们的接口来获取 IP 详细信息喵:</p> <div class="bg-pink-50 p-4 rounded-xl border border-pink-100 font-mono text-xs overflow-x-auto text-pink-700 shadow-inner"> GET https://api.maoniang.example/v1/ip?address=<span class="text-rose-500">{ip}</span> </div> <p class="font-bold text-gray-700 mt-4">📦 返回数据格式示例 (JSON):</p> <pre class="bg-slate-800 text-pink-200 p-4 rounded-xl text-xs overflow-x-auto font-mono shadow-inner leading-relaxed"> { "code": 200, "msg": "success", "data": { "country": "美国", "province": "加利福尼亚州", "city": "圣克拉拉", "isp": "阿里云", "latitude": "37.355701", "longitude": "-121.955002" } }</pre> </div> <div class="mt-8 text-center"> <button id="close-modal-bottom" class="bg-pink-100 hover:bg-pink-200 text-pink-600 font-bold py-2.5 px-8 rounded-full transition-colors active:scale-95 shadow-sm"> 我知道了喵 🐾 </button> </div> </div> </div> <!-- 交互逻辑 --> <script> document.addEventListener('DOMContentLoaded', () => { const currentIpSpan = document.getElementById('current-ip'); const searchBtn = document.getElementById('search-btn'); const ipInput = document.getElementById('ip-input'); // 结果节点 const resCountry = document.getElementById('res-country'); const resProvince = document.getElementById('res-province'); const resCity = document.getElementById('res-city'); const resIsp = document.getElementById('res-isp'); const resLatlon = document.getElementById('res-latlon'); // 弹窗相关节点 const apiModal = document.getElementById('api-modal'); const apiModalOverlay = document.getElementById('api-modal-overlay'); const apiModalContent = document.getElementById('api-modal-content'); const apiInfoBtn = document.getElementById('api-info-btn'); const closeModalTop = document.getElementById('close-modal-top'); const closeModalBottom = document.getElementById('close-modal-bottom'); // 1. 获取用户当前IP (使用免费的 ipify API) fetch('https://api.ipify.org?format=json') .then(response => response.json()) .then(data => { currentIpSpan.textContent = data.ip; }) .catch(error => { currentIpSpan.textContent = "获取失败喵 T_T"; console.error('获取IP失败:', error); }); // ================= 弹窗控制逻辑 ================= const openModal = () => { apiModal.classList.remove('hidden'); // 强制重绘以触发动画 void apiModal.offsetWidth; apiModalOverlay.classList.remove('opacity-0'); apiModalOverlay.classList.add('opacity-100'); apiModalContent.classList.remove('opacity-0', 'scale-95'); apiModalContent.classList.add('opacity-100', 'scale-100'); }; const closeModal = () => { apiModalOverlay.classList.remove('opacity-100'); apiModalOverlay.classList.add('opacity-0'); apiModalContent.classList.remove('opacity-100', 'scale-100'); apiModalContent.classList.add('opacity-0', 'scale-95'); // 等待动画结束后隐藏元素 setTimeout(() => { apiModal.classList.add('hidden'); }, 300); // 对应 duration-300 }; apiInfoBtn.addEventListener('click', openModal); closeModalTop.addEventListener('click', closeModal); closeModalBottom.addEventListener('click', closeModal); apiModalOverlay.addEventListener('click', closeModal); // 点击遮罩层也可关闭 // 2. 点击查询按钮的逻辑 searchBtn.addEventListener('click', () => { const ipToSearch = ipInput.value.trim(); if (!ipToSearch) { alert('请输入要查询的 IP 地址喵!'); return; } // 添加加载动画效果 searchBtn.innerHTML = '查询中... 🐾'; searchBtn.classList.add('opacity-80', 'cursor-not-allowed'); setTimeout(() => { // 适配你提供的 JSON 格式模拟返回数据 const mockData = { "country": "美国", "province": "加利福尼亚州", "city": "圣克拉拉", "isp": "阿里云", "latitude": "37.355701", "longitude": "-121.955002" }; // 更新 DOM 数据 resCountry.textContent = mockData.country; resProvince.textContent = mockData.province; resCity.textContent = mockData.city; resIsp.textContent = mockData.isp; resLatlon.textContent = `${mockData.latitude}, ${mockData.longitude}`; // 恢复按钮状态 searchBtn.innerHTML = '查询喵 🐾'; searchBtn.classList.remove('opacity-80', 'cursor-not-allowed'); // 小彩蛋互动 ipInput.value = ''; ipInput.placeholder = '查询成功了喵!继续输入吧~'; }, 600); // 模拟网络延迟 }); // 支持回车查询 ipInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') { searchBtn.click(); } }); }); </script> </body> </html>但是仔细观察,你会发现使用了实时构建的 Tailwind CSS ,其实这样做对于一个静态页面不太友好,于是我让他按照 Tailwind CSS 的样式,原生帮我写了一版样式。因为处理后代码变多了,我就不在这里放出来了。最后静态文件就三个:[chocola@Neko-X99 static]$ tree . ├── favicon.png ├── index.html └── main.css 1 directory, 3 files后端设计因为项目的定位是轻量,所以我不打算依赖外部的数据库。再加上IP查询这个业务场景几乎全是读操作,所以使用SQLite是没问题的,读取这方面没有瓶颈。为了实现高效的 IP 查询,数据库表结构的设计至关重要。核心思路是将文本格式的 IP 地址转换为无符号 32 位整数(uint32),这样不仅运算效率高,也便于进行范围比较。数据库表(例如 ip_info)主要包含三个字段:network_start (INTEGER): 存储该 IP 段的起始地址,以 uint32 格式保存。这是查询的核心,我们会根据这个字段建立索引(CREATE INDEX idx_network_start ON ip_info (network_start);),以确保查询性能。network_end (INTEGER): 存储该 IP 段的结束地址,同样以 uint32 格式保存。用于在查找到候选记录后,进行二次验证,确保目标 IP 确实落在该网段内。ip_info_json (TEXT): 将该 IP 段对应的地理位置、运营商等详细信息,序列化成 JSON 字符串后存储在此字段。这种方案灵活度高,可以方便地增减返回的字段,而无需修改表结构。查询时,我们首先将待查询的 IP 转换为整数,然后利用 WHERE network_start <= ? ORDER BY network_start DESC LIMIT 1 这样的 SQL 语句,借助索引快速定位到最接近且小于等于目标 IP 的那条记录。接着,再用 network_end 字段验证目标 IP 是否在该记录的范围内,从而得出最终结果。这种“先定位,后校验”的方式,配合索引,能够将查询耗时稳定在微秒级别。测试环境:CPU:i5-2410M内存:4GB DDR3 1600MHz硬盘:希捷 320G SATA2 机械硬盘Nginx:模拟真实环境,开启SSL进行反代第一版代码package main import ( "database/sql" "encoding/json" "flag" "fmt" "log" "net" "net/http" "strings" _ "github.com/mattn/go-sqlite3" ) var db *sql.DB // 定义完全匹配前端需求的数据结构 type IPInfo struct { IP string `json:"ip"` Country string `json:"country"` Province string `json:"province"` City string `json:"city"` ISP string `json:"isp"` Latitude string `json:"latitude"` Longitude string `json:"longitude"` } // 定义标准的 API 响应格式 type APIResponse struct { Code int `json:"code"` Msg string `json:"msg"` Data interface{} `json:"data"` // 用 interface{} 以便在出错时返回 nil } // 辅助函数:获取客户端真实 IP func getClientIP(r *http.Request) string { ip := r.Header.Get("X-Real-IP") if ip == "" { ip = r.Header.Get("X-Forwarded-For") } if ip == "" { ip, _, _ = net.SplitHostPort(r.RemoteAddr) } // X-Forwarded-For 可能是逗号分隔的多个IP,取第一个真实的 ip = strings.Split(ip, ",")[0] // 清理可能包含的空格,提升健壮性 return strings.TrimSpace(ip) } func apiHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.Header().Set("Access-Control-Allow-Origin", "*") // 提取查询参数并去除两端空白字符 queryIPStr := strings.TrimSpace(r.URL.Query().Get("ip")) targetIP := queryIPStr if targetIP == "" { targetIP = getClientIP(r) } // 【安全防线 1】:严格限制为合法的 IPv4 格式。任何注入代码都会在这里被直接拦截。 parsedIP := net.ParseIP(targetIP) if parsedIP == nil || parsedIP.To4() == nil { json.NewEncoder(w).Encode(APIResponse{Code: 400, Msg: "非法的 IPv4 地址喵!", Data: nil}) return } // 【安全防线 2】:转为 uint32 整型。彻底杜绝字符型注入。 ipInt := uint32(parsedIP.To4()[0])<<24 | uint32(parsedIP.To4()[1])<<16 | uint32(parsedIP.To4()[2])<<8 | uint32(parsedIP.To4()[3]) var infoJSON string var networkEnd uint32 // 🌟 记得提前声明这个变量喵 // 【性能优化核心】:利用索引极速向下查找最近的一条记录 err := db.QueryRow(` SELECT network_end, ip_info_json FROM ip_info WHERE network_start <= ? ORDER BY network_start DESC LIMIT 1`, ipInt).Scan(&networkEnd, &infoJSON) if err != nil { if err == sql.ErrNoRows { json.NewEncoder(w).Encode(APIResponse{Code: 404, Msg: "数据库里没有找到这个 IP 喵~", Data: nil}) } else { // 避免将底层的数据库错误直接暴露给前端(防止信息泄露) log.Printf("数据库查询错误: %v\n", err) json.NewEncoder(w).Encode(APIResponse{Code: 500, Msg: "数据库查询出错了喵", Data: nil}) } return } // 【关键逻辑校验】:虽然找到了最近的起始 IP,但必须确认目标 IP 是否在这个网段的覆盖范围内 if ipInt > networkEnd { json.NewEncoder(w).Encode(APIResponse{Code: 404, Msg: "数据库里没有找到这个 IP 喵~", Data: nil}) return } var rawData map[string]string if err := json.Unmarshal([]byte(infoJSON), &rawData); err != nil { log.Printf("JSON 解析错误: %v\n", err) json.NewEncoder(w).Encode(APIResponse{Code: 500, Msg: "数据解析失败喵", Data: nil}) return } result := IPInfo{ IP: targetIP, Country: rawData["country"], Province: rawData["province"], City: rawData["city"], ISP: rawData["isp"], Latitude: rawData["latitude"], Longitude: rawData["longitude"], } json.NewEncoder(w).Encode(APIResponse{ Code: 200, Msg: "success", Data: result, }) } func main() { // ================= 定义启动参数 ================= // flag.String("参数名", "默认值", "说明文字") dbPath := flag.String("db", "ip_info.db", "SQLite 数据库文件路径") port := flag.String("port", "8080", "API 服务监听端口") // 解析命令行参数 flag.Parse() var err error // 使用参数指定的数据库路径 db, err = sql.Open("sqlite3", *dbPath) if err != nil { log.Fatal("无法打开数据库: ", err) } defer db.Close() http.HandleFunc("/ipinfo", apiHandler) // 拼接监听地址 addr := fmt.Sprintf(":%s", *port) fmt.Printf("猫娘纯净 API 服务启动于 %s 喵... 🐾\n", addr) fmt.Printf("当前使用的数据库文件: %s\n", *dbPath) log.Fatal(http.ListenAndServe(addr, nil)) } content_copy测试下来直接就踩了一个大坑:因为没有设置索引,数据库查询效率非常低下,以至于到了难以置信的慢。通过这个命令:CREATE INDEX idx_network_start ON ip_info (network_start); content_copy建立好索引后,查询速度直接起飞。从原来每秒只能处理10个请求飙升至每秒可以处理5000+个请求,性能直接翻了500倍!太夸张了!第二版代码虽然第一版代码的性能已经可以做到很优秀,但是我还是希望尝试进一步优化,那就是——数据库存入内存!而而且我不但要存入内存,还要将其转化为Go原生的数据存储格式,进一步优化性能。package main import ( "database/sql" "encoding/json" "flag" "fmt" "log" "net" "net/http" "sort" "strings" "time" _ "github.com/mattn/go-sqlite3" ) var db *sql.DB // --- 全局配置与缓存 --- var ( ipCache []IPRule // 全量内存切片 useMemoryCache bool // 内存模式开关 enableDetailLog bool // 详细日志开关 ) type IPRule struct { NetworkStart uint32 NetworkEnd uint32 Info IPInfo } type IPInfo struct { IP string `json:"ip"` Country string `json:"country"` Province string `json:"province"` City string `json:"city"` ISP string `json:"isp"` Latitude string `json:"latitude"` Longitude string `json:"longitude"` } type APIResponse struct { Code int `json:"code"` Msg string `json:"msg"` Data interface{} `json:"data"` } // 辅助函数:获取客户端真实 IP func getClientIP(r *http.Request) string { ip := r.Header.Get("X-Real-IP") if ip == "" { ip = r.Header.Get("X-Forwarded-For") } if ip == "" { ip, _, _ = net.SplitHostPort(r.RemoteAddr) } ip = strings.Split(ip, ",")[0] return strings.TrimSpace(ip) } // 统一处理响应和日志打印 func sendJSONResponse(w http.ResponseWriter, clientIP, targetIP string, resp APIResponse) { w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Header().Set("Access-Control-Allow-Origin", "*") // 将结构体序列化为 JSON 字节 respBytes, err := json.Marshal(resp) if err != nil { log.Printf("响应序列化失败: %v", err) http.Error(w, `{"code":500,"msg":"系统内部错误","data":null}`, http.StatusInternalServerError) return } // 如果开启了日志,就在这里统一输出 if enableDetailLog { log.Printf("[访问日志] 来源IP: %-15s | 查询IP: %-15s | 结果: %s", clientIP, targetIP, string(respBytes)) } // 写入响应 w.Write(respBytes) } func loadDataToMemory() error { log.Println("正在将数据库载入内存,请稍候喵...") startTime := time.Now() rows, err := db.Query(`SELECT network_start, network_end, ip_info_json FROM ip_info ORDER BY network_start ASC`) if err != nil { return err } defer rows.Close() for rows.Next() { var start, end uint32 var infoJSON string if err := rows.Scan(&start, &end, &infoJSON); err != nil { return err } var rawData map[string]string if err := json.Unmarshal([]byte(infoJSON), &rawData); err != nil { continue } info := IPInfo{ Country: rawData["country"], Province: rawData["province"], City: rawData["city"], ISP: rawData["isp"], Latitude: rawData["latitude"], Longitude: rawData["longitude"], } ipCache = append(ipCache, IPRule{ NetworkStart: start, NetworkEnd: end, Info: info, }) } log.Printf("载入完成!共加载了 %d 条规则,耗时 %v 喵!", len(ipCache), time.Since(startTime)) return nil } func apiHandler(w http.ResponseWriter, r *http.Request) { clientIP := getClientIP(r) // 提取实际访问者的 IP,用于日志记录 queryIPStr := strings.TrimSpace(r.URL.Query().Get("ip")) targetIP := queryIPStr if targetIP == "" { targetIP = clientIP } parsedIP := net.ParseIP(targetIP) if parsedIP == nil || parsedIP.To4() == nil { sendJSONResponse(w, clientIP, targetIP, APIResponse{Code: 400, Msg: "非法的 IPv4 地址喵!", Data: nil}) return } ipInt := uint32(parsedIP.To4()[0])<<24 | uint32(parsedIP.To4()[1])<<16 | uint32(parsedIP.To4()[2])<<8 | uint32(parsedIP.To4()[3]) if useMemoryCache { idx := sort.Search(len(ipCache), func(i int) bool { return ipCache[i].NetworkStart > ipInt }) if idx > 0 { rule := ipCache[idx-1] if ipInt <= rule.NetworkEnd { result := rule.Info result.IP = targetIP sendJSONResponse(w, clientIP, targetIP, APIResponse{Code: 200, Msg: "success", Data: result}) return } } sendJSONResponse(w, clientIP, targetIP, APIResponse{Code: 404, Msg: "内存库里没有找到这个 IP 喵~", Data: nil}) } else { var infoJSON string var networkEnd uint32 err := db.QueryRow(` SELECT network_end, ip_info_json FROM ip_info WHERE network_start <= ? ORDER BY network_start DESC LIMIT 1`, ipInt).Scan(&networkEnd, &infoJSON) if err != nil { if err == sql.ErrNoRows { sendJSONResponse(w, clientIP, targetIP, APIResponse{Code: 404, Msg: "数据库里没有找到这个 IP 喵~", Data: nil}) } else { log.Printf("数据库查询错误: %v\n", err) sendJSONResponse(w, clientIP, targetIP, APIResponse{Code: 500, Msg: "数据库查询出错了喵", Data: nil}) } return } if ipInt > networkEnd { sendJSONResponse(w, clientIP, targetIP, APIResponse{Code: 404, Msg: "数据库里没有找到这个 IP 喵~", Data: nil}) return } var rawData map[string]string if err := json.Unmarshal([]byte(infoJSON), &rawData); err != nil { log.Printf("JSON 解析错误: %v\n", err) sendJSONResponse(w, clientIP, targetIP, APIResponse{Code: 500, Msg: "数据解析失败喵", Data: nil}) return } result := IPInfo{ IP: targetIP, Country: rawData["country"], Province: rawData["province"], City: rawData["city"], ISP: rawData["isp"], Latitude: rawData["latitude"], Longitude: rawData["longitude"], } sendJSONResponse(w, clientIP, targetIP, APIResponse{Code: 200, Msg: "success", Data: result}) } } func main() { dbPath := flag.String("db", "ip_info.db", "SQLite 数据库文件路径") port := flag.String("port", "8080", "API 服务监听端口") memFlag := flag.Bool("mem", false, "是否开启全量内存模式(内存换取极致性能喵~)") logFlag := flag.Bool("log", false, "是否开启详细访问日志输出") flag.Parse() useMemoryCache = *memFlag enableDetailLog = *logFlag // 赋值给全局变量 var err error db, err = sql.Open("sqlite3", *dbPath) if err != nil { log.Fatal("无法打开数据库: ", err) } defer db.Close() if useMemoryCache { if err := loadDataToMemory(); err != nil { log.Fatal("致命错误:无法将数据加载到内存喵: ", err) } } http.HandleFunc("/ipinfo", apiHandler) addr := fmt.Sprintf(":%s", *port) fmt.Printf("猫娘 API 服务启动于 %s 喵...\n", addr) fmt.Printf("当前数据库文件: %s\n", *dbPath) if useMemoryCache { fmt.Println("当前运行模式: [极致性能] 全量内存 + 二分查找") } else { fmt.Println("当前运行模式: [省内存] SQLite 实时查询 (可加 -mem=true 提速)") } if enableDetailLog { fmt.Println("详细访问日志: 已开启 (将在控制台打印每次请求细节)") } else { fmt.Println("详细访问日志: 未开启 (可加 -log=true 开启)") } log.Fatal(http.ListenAndServe(addr, nil)) }另外,我还加上了日志输出的功能,方便进行API调用的监控,可以防范滥用。经过测试,在把数据库存进内存后,可以抗的并发请求从 5000+ 请求/秒 提升到了 7000+ 请求/秒,提升了40%!不过我也观察到,此时Nginx的CPU占用率明显上升,大约占据了40%+的CPU,而Go程序本身的CPU占用率则从50%左右降低到了35%!不过有点奇怪的是,大约有20%的CPU占用率不知道是被什么程序占据了,BTOP没有显示出来。其实在第一版代码的时候,Nginx的CPU占用已经挺高了,请求数量提升后更高。值得注意的是,两个版本的服务端进行极限压力测试的时候,整机的CPU占用率几乎都是100%。不知道各位对这个性能表现感觉如何?分析:“消失”的20% CPU占用去哪了?在测试中,我观察到一个有趣的现象:Nginx 占用了约 40%,Go 程序占用了约 35%,加起来只有 75% 左右,但整机 CPU 却已经打满(100%)。剩下的 20% 去哪了?难道被猫娘偷吃了吗?其实,这并非 BUG,而是高性能网络服务的典型特征——内核态开销(System CPU)。当 QPS 达到 7000+ 时,服务器每秒需要处理数万个网络数据包的接收、发送、上下文切换以及系统调用。这些操作并不发生在 Nginx 或 Go 程序的“用户态”代码中,而是直接由 Linux 内核 接管处理:网络协议栈处理:TCP/IP 包的解析、校验、重组。软中断(SoftIRQs):网卡中断后的数据搬运。线程调度:在数千个并发连接间快速切换 CPU 时间片。结论:这“消失”的 20% 实际上是被 操作系统内核 消耗掉了,用于支撑如此高频率的网络吞吐。这也侧面证明了我们的程序优化已经非常到位,瓶颈不再在于应用层代码,而在于底层的网络 IO 处理能力。如果再想提升,可能就需要考虑内核参数调优(如调整 TCP 缓冲区、开启 RSS 多队列网卡等)或者升级更强的单核 CPU 了喵!提升程序的兼容性因为我们的项目依赖了go-sqlite3,这要求必须开启CGO进行编译。如果在一般的Linux发行版(如Ubuntu、CentOS)上直接编译,默认会动态链接系统的C语言标准库(glibc)。这必然会导致把程序放到不同年代、不同发行版的服务器上运行时,出现“找不到glibc版本”等兼容性报错。为了达到“一次编译,到处运行”的完美兼容性,我们需要进行纯静态链接打包。但是,在普通发行版上强行静态编译 glibc 是非常痛苦且容易踩坑的。因此,我们需要借助musl这个极其精简的C标准库。使用musl的典型代表就是Alpine Linux(这也是老朋友了,我的云服务器基本上都是这个发行版)。我们可以非常优雅地在 Alpine 环境下进行全静态编译操作:先安装必要的 C 语言编译工具链:apk add go gcc musl-dev content_copy进入代码目录后,初始化模块并拉取依赖:go mod init github.com/Chocola-X/NekoIPinfo go mod tidy content_copy最后,使用“静态编译参数”进行编译:CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -ldflags="-linkmode external -extldflags -static -s -w" -o neko-ip-api main.go content_copy这样编译出来的二进制文件内部已经打包了所有需要的底层库。你把它丢到绝大部分 x86_64 架构的 Linux 发行版上,都可以做到直接开箱即用!结尾项目已经开源到了Github:NekoIPinfo并且我也自己搭建了查询服务,感兴趣的可以来玩玩:NekoIPinfo Demo
2026年03月06日
3 阅读
0 评论
0 点赞
1
...
39
40