跳到主要内容

Go println 和 fmtPrintln 对比

· 阅读需 2 分钟
素明诚
Full stack development
特性println()fmt.Println()
来源Go 语言的内建函数,无需导入需要导入 fmt 包
用途主要用于开发阶段的快速调试适用于生产环境,支持复杂的输出需求
格式化能力无法自定义输出格式支持广泛的格式化选项,如数字格式、宽度、精度等
输出控制自动在输出元素之间添加空格,结尾自动换行自动在输出元素之间添加空格,结尾自动换行,格式化更灵活
性能通常较快但差异通常不显著性能优秀,适用于高频输出场景
依赖性不依赖任何外部包,始终可用依赖于 fmt 包,需要导入使用
输出示例println("Hello", "world") 输出:Hello worldfmt.Println("Hello", "world") 输出:Hello world
适用场景简单脚本、学习阶段、快速调试生产代码、需要格式化输出的场景、日志记录等
控制台交互较为简单,无法处理复杂的用户输出交互可以与 fmt.Scanln() 等输入函数配合使用,适合复杂的控制台交互
推荐使用开发早期、调试、教学示例生产环境、需要格式化或多样化输出的应用

格式化输出

print

func main() {
name := "Alice"
age := 30
println("Name:", name, "Age:", age)
}

Println

func main() {
name := "Alice"
age := 30
fmt.Printf("Name: %s, Age: %d\n", name, age)
}

使用切片和复杂数据结构

package main

import "fmt"

func main() {
numbers := []int{1, 2, 3}
// 快速检查切片的地址或确认切片非空。
println("Numbers:", numbers) // Numbers: [3/3]0xc000010108
// 能够直接输出切片内容及其结构,适合在处理数据和调试复杂结构时使用。
fmt.Println("Numbers:", numbers) // Numbers: [1 2 3]
}

Go 五种字符串连接方式

· 阅读需 1 分钟
素明诚
Full stack development
package main

import (
"bytes"
"fmt"
"strings"
)

// 使用 + 连接字符串
func joinWithPlus(s1, s2 string) string {
return s1 + s2
}

// 使用 fmt.Sprintf 连接字符串
func joinWithSprintf(s1, s2 string) string {
return fmt.Sprintf("%s%s", s1, s2)
}

// 使用 strings.Builder 连接字符串
func joinWithBuilder(s1, s2 string) string {
var builder strings.Builder
builder.WriteString(s1)
builder.WriteString(s2)
return builder.String()
}

// 使用 strings.Join 连接字符串切片
func joinWithJoin(
elements []string,
sep string,
) string {
return strings.Join(elements, sep)
}

// 使用 bytes.Buffer 连接字符串
func joinWithBuffer(s1, s2 string) string {
var buffer bytes.Buffer
buffer.WriteString(s1)
buffer.WriteString(s2)
return buffer.String()
}

func main() {
s1 := "Hello, "
s2 := "world!"
elements := []string{s1, s2}

// 使用 + 连接
// 小需求场景下使用 + 连接字符串
fmt.Println("Join with +:", joinWithPlus(s1, s2))

// 使用 fmt.Sprintf 连接
fmt.Println("Join with fmt.Sprintf:", joinWithSprintf(s1, s2))

// 使用 strings.Builder 连接
// 此方法最高效 但是需要 Go 1.10 以上版本 是专门为高效构建和连接大量字符串而设计的
fmt.Println("Join with strings.Builder:", joinWithBuilder(s1, s2))

// 使用 strings.Join 连接
fmt.Println("Join with strings.Join:", joinWithJoin(elements, ""))

// 使用 bytes.Buffer 连接
fmt.Println("Join with bytes.Buffer:", joinWithBuffer(s1, s2))
}

Go 内建函数

· 阅读需 1 分钟
素明诚
Full stack development

内建函数(built-in functions)是指在编程语言中预定义的、可以直接使用而不需要额外导入库或模块的函数。这些函数是编程语言的一部分,通常提供基本的或最常用的功能,以方便开发者在不引入外部依赖的情况下完成基础或核心的任务。

常见内建函数

类型操作:比如 int()float64() 用于类型转换,type 用于类型断言。

处理数据len() 可获取切片、映射、字符串、数组或通道的长度,cap() 查看切片或数组的容量。另外,append()copy() 分别用于向切片添加元素和复制切片内容。

创建和初始化make()new() 分别用于初始化切片、映射、通道,以及分配内存。

复杂数据操作delete() 可从映射中删除键值对。

并发控制go 关键字用来启动新的协程,而 select 处理多个通道的接收操作。

错误处理panic() 用于触发运行时错误,而 recover() 可以从这种错误中恢复。

Go 切片操作

· 阅读需 3 分钟
素明诚
Full stack development

切片的基本概念

切片是 Go 语言中一个动态数组的引用类型,提供了一种灵活、高效的方式来处理数据集合。它不存储任何数据,只是对底层数组的一个连续片段的描述,包括三个部分 指向数组的指针、切片的长度和容量。

切片创建和索引

两个参数的切片(arr[start:end])

当使用两个参数对数组或已存在的切片进行切片操作时

  • 长度(len)end - start 计算得出,表示切片覆盖的元素数量。
  • 容量(cap) 从切片的起始索引到原数组或原切片末尾的元素数量。计算方式是原数组或切片的长度减去切片的起始索引。
arr := [5]int{1, 2, 3, 4, 5}
s := arr[1:3]
// s 包含元素 [2, 3]
// len(s) == 2
// cap(s) == 4 (从索引1到数组末尾)

三个参数的切片(arr[start:end:cap])

使用三个参数进行切片操作可以更精确地控制切片的容量

  • 第三个参数(容量上限) 定义了切片从起始索引开始能扩展到的数组或切片的最远边界的索引。
  • 切片的实际容量由 cap - start 计算得出,但不能超过从起始索引到原数组或原切片末尾的长度。
arr := [5]int{1, 2, 3, 4, 5}
t := arr[1:3:4]
// t 包含元素 [2, 3]
// len(t) == 2
// cap(t) == 3 (从索引1开始,可以扩展到索引4之前)

切片的行为

  • 不修改原始数组 通过切片操作不会修改底层数组的内容,切片仅作为对数组某部分的引用。
  • 切片的修改影响数组 如果通过切片修改了元素,同样的修改会反映在底层数组上。
  • 切片扩展 切片可以通过 append() 函数进行扩展,但是如果扩展后的长度超过了切片的容量,Go 语言运行时会分配一个新的数组来存储数据,原有数组的内容会被复制到新数组中。

使用场景和注意事项

  • 使用两个参数的切片适用于简单的数据访问和部分修改,而三个参数的切片适用于需要严格控制切片容量和安全性的场景,如并发编程中防止切片操作影响到原数组的其他部分。
  • 切片的容量控制尤其重要,因为它影响着切片的扩展能力和性能表现。

什么是 RAG检索增强生成

· 阅读需 2 分钟
素明诚
Full stack development

检索增强生成(Retrieval-Augmented Generation, RAG)

数据预处理和文档摄取:首先,从各种数据源(如数据库、文档或实时数据源)收集原始数据。这些数据经过预处理,如文本分割,以适应嵌入模型的要求。这一步骤确保数据可以被系统高效处理。也是最最重要的一步,数据好才能有好的生成结果。

生成嵌入向量:预处理后的数据需要转换成向量形式。这些向量是通过嵌入模型生成的,代表了文本的数值形式,使得检索模型能够快速识别相关数据点。

向量数据库存储:生成的嵌入向量存储在专门的向量数据库中,这些数据库优化了搜索和检索操作,确保信息随时可访问,并能在实时交互中快速检索。

使用大型语言模型(LLM)生成响应:当用户提交查询时,系统利用索引数据和向量执行高效搜索,检索相关信息。然后,LLM 使用检索到的数据来制定恰当的响应。

优化和安全措施:为了提高系统性能,可以通过 GPU 加速数据预处理、索引和检索过程。此外,考虑数据安全,特别是在企业环境下,通过角色基于访问控制(RBAC)等措施,确保数据的安全。

向量搜索数据库选择

Faiss: 由 Facebook AI Research 开发,Faiss 针对密集向量的相似性搜索和聚类进行了专门的优化。它特别适合进行高维向量搜索,且支持 GPU 加速,使其在处理大量数据集时显著提高了效率。

Elasticsearch with Vector Search Plugin: 作为一款支持全文和结构化搜索的开源搜索引擎,Elasticsearch 通过引入向量搜索插件(比如自身的向量打分功能或是第三方插件),也实现了高效的向量搜索能力。

Milvus: 作为一个开源的向量数据库,Milvus 支持存储、检索以及分析大规模向量数据。它提供了多种索引类型的支持,并且能够进行无缝扩展,非常适合企业级的应用场景。

标签:

重写 JS 数组方法

· 阅读需 4 分钟
素明诚
Full stack development

这篇文章汇总了当前已实现的数组方法。未实现的方法将在后续更新中补充到本文中。如果你希望检验自己的基础知识,也可以根据本文提供的表格逐一尝试实现这些数组方法。已实现的会插入超链接~

数组方法实现难度

方法名描述难度评级
push()向数组的末尾添加一个或更多元素,并返回新的长度。
pop()移除数组最后一个元素,并返回该元素。
shift()从数组中删除第一个元素,并返回该元素。
unshift()向数组的开头添加一个或多个元素,并返回新的长度。
indexOf()返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。
lastIndexOf()返回数组中最后出现的指定元素的索引,如果未找到则返回 -1。
join()将所有数组元素连接成一个字符串并返回。
reverse()颠倒数组中元素的顺序。
includes()判断数组是否包含一个指定的值。
slice()返回数组的一个片段或子数组。
concat()合并两个或多个数组,并返回一个新数组。
splice()在数组中添加或删除元素,并返回被删除的元素。
toString()返回一个字符串表示数组中的元素。
toLocaleString()返回一个字符串表示数组中的元素。本地化的字符串表示形式。
fill()用一个固定值填充数组中从起始索引到终止索引的全部元素。
map()创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后的返回值。
filter()创建一个新数组, 其包含通过所提供函数测试的所有元素。
every()检测数组所有元素是否都符合指定条件。
some()检测数组中的某些元素是否满足指定条件。
find()返回数组中满足提供的测试函数的第一个元素的值。
findIndex()返回数组中满足提供的测试函数的第一个元素的索引。
findLast()返回数组中最后一个满足所提供测试函数的元素。
findLastIndex()返回数组中最后一个满足所提供测试函数的元素的索引。
reduce()对数组中的每个元素执行一个用户提供的 reducer 函数(升序执行),从左到右。
reduceRight()对数组中的每个元素执行一个用户提供的 reducer 函数(降序执行),从右到左。
flatMap()先对数组的每个元素执行一个映射函数,然后将结果压平成一个新数组。
flat()将所有嵌套数组的元素连接成一个新数组。
copyWithin()在数组内部,将一系列元素按序复制到另一个起始位置,并返回数组。
sort()对数组的元素进行排序。
entries()返回一个新的 Array Iterator 对象,包含数组中每个索引的键/值对。
keys()返回一个新的 Array Iterator,包含数组中每个索引的键。
values()返回一个新的 Array Iterator 对象,包含数组每个索引的值。
forEach()对数组的每个元素执行一次给定的函数。

如果你喜欢这篇文章请点个赞再走吧~

Nextjs 快速上手

· 阅读需 5 分钟
素明诚
Full stack development

阅读本文希望你有一定的前端基础,Next.js 了解以下几点即可快速上手,有问题的话就边做边解决~

文件系统路由

Next.js 通过 pages 目录中的文件和文件夹结构自动设置路由。你创建出来的每一个 React 组件文件都被视为一个路由。

如果你有一个博客,你可能需要为每篇文章创建一个页面。在 pages 目录下,你可以创建一个名为 posts 的文件夹,然后在其中创建一个名为 [id].js 的文件。这里的 [id] 表示动态的路由部分。

// pages/posts/[id].js
import { useRouter } from 'next/router';

function Post() {
const router = useRouter();
const { id } = router.query;

return <p>Post: {id}</p>;
}

export default Post;

预渲染和数据获取

Next.js 支持两种形式的预渲染:静态生成(Static Generation)和服务器端渲染(Server-side Rendering)

静态生成(Static Generation)

静态生成是在构建时生成 HTML 的过程(也就是执行 next build 命令时)。这意味着页面在构建时就被渲染好,并且在每个请求中重复使用。这种方式非常适合内容不频繁更改的页面。

示例:使用 getStaticProps 为博客首页获取文章列表

// pages/index.js
export async function getStaticProps() {
// 模拟从外部API获取数据
const res = await fetch('https://api.example.com/posts');
const posts = await res.json();

// 将获取的文章数据通过props传递给页面组件
return {
props: { posts },
revalidate: 10, // 在生产模式下,每10秒重新生成页面一次
};
}

function HomePage({ posts }) {
return (
<div>
<h1>Latest Blog Posts</h1>
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}

export default HomePage;

这个例子中,getStaticProps 在构建时调用,获取所有的博文,然后保存在页面的 HTML 中。通过设置 revalidate,你可以使页面在一定时间后重新生成,以便更新内容。

服务器端渲染(Server-side Rendering)

服务器端渲染是每次请求时都生成 HTML 的过程。这种方法适合内容频繁更新的页面,或者内容在每次请求时都可能不同的情况。

示例:使用 getServerSideProps 显示用户个人信息页面,这个信息依赖于每次请求的用户身份。

// pages/profile.js
export async function getServerSideProps(context) {
const { req } = context;
const userId = req.cookies.userId; // 假设用户ID存储在cookies中

const res = await fetch(`https://api.example.com/users/${userId}`);
const userData = await res.json();

return {
props: { user: userData }
};
}

function ProfilePage({ user }) {
return (
<div>
<h1>User Profile</h1>
<p>Name: {user.name}</p>
<p>Email: {user.email}</p>
</div>
);
}

export default ProfilePage;

这个例子中,getServerSideProps 在每次页面请求时执行,从 API 获取当前用户的数据,并将其作为 props 传递给页面。这确保了用户看到的总是最新的信息。

API 路由

假设你有一个处理特定用户的 API 路由,文件路径为 pages/api/users/[id].js

// pages/api/users/[id].js
export default function handler(req, res) {
const { query: { id }, method } = req;

switch (method) {
case 'GET':
// 获取特定用户的信息
res.status(200).json({ id, name: "John Doe" });
break;
case 'PUT':
// 更新特定用户的信息
res.status(200).json({ id, name: "John Doe Updated" });
break;
case 'DELETE':
// 删除特定用户
res.status(200).json({ message: `User ${id} deleted.` });
break;
default:
// 不支持其他方法
res.setHeader('Allow', ['GET', 'PUT', 'DELETE']);
res.status(405).end(`Method ${method} Not Allowed`);
}
}


CSS 支持

Next.js 支持 CSS Modules,允许你使用局部作用域的 CSS。

// styles/Home.module.css
.home {
color: blue;
}

// pages/index.js
import styles from '../styles/Home.module.css';

function HomePage() {
return <div className={styles.home}>Welcome to the HomePage</div>;
}

export default HomePage;

图像优化

Next.js 提供了内置的 Image 组件,用于自动优化图像加载。推荐使用

示例:使用 Image 组件

import Image from 'next/image';

function MyImageComponent() {
return (
<Image
src="/me.png"
alt="Picture of the author"
width={500}
height={500}
/>
);
}

环境变量

管理应用的环境变量,如 API 密钥或数据库 URL,Next.js 提供了一个简单的方式来加载和使用环境变量。

// 在 .env.local 文件中设置
API_SECRET_KEY=your_secret_key

// 在代码中使用
process.env.API_SECRET_KEY

配置不同环境的环境变量

  • .env.local - 存放本地开发环境特有的变量,通常不应该提交到版本控制系统。
  • .env - 存放所有环境通用的变量。
  • .env.development, .env.test, .env.production - 分别用于开发、测试和生产环境的特定变量。

您可以通过设置 NODE_ENV 环境变量来指定当前环境。这通常在启动应用时完成

  • 在本地开发环境,NODE_ENV 通常默认为 development
  • 在生产环境部署时,应将 NODE_ENV 设置为 production
  • 对于测试环境,可以设置为 test

在命令行中启动应用时,可以这样设置环境变量

NODE_ENV=production npm run build

动态导入

Next.js 支持 JavaScript 和组件的动态导入,这有助于减少初始加载时间并按需加载功能。类似于 vue-router 的异步加载。这个特性都是用来实现代码拆分和按需加载,从而优化应用的初始加载时间和总体性能。

import dynamic from 'next/dynamic';

const DynamicComponent = dynamic(() => import('../components/hello'));

function Home() {
return (
<div>
<DynamicComponent />
</div>
);
}

export default Home;

样式

CSS 和模块:全局 CSS 文件只能在 _app.js_app.tsx 中导入,但 CSS 模块(.module.css)可以在组件的任何地方导入,以提供作用域样式。

特殊文件

pages/_app.js:允许你用布局和全局样式初始化页面。这个文件用于在页面间导航时保持状态。

pages/_document.js:用于自定义 HTML 文档结构,常用于增强应用的 <html><body> 标签。

pages/_error.js:用于覆盖 Next.js 提供的默认错误页面。

如果您喜欢这篇文章,不妨给它点个赞并收藏,感谢您的支持!

Web 响应式设计缩写和尺寸

· 阅读需 1 分钟
素明诚
Full stack development
名称缩写描述
像素px固定单位,一个像素点的大小。
百分比%相对单位,基于父元素的相应属性值的百分比。
视口宽度单位vw相对单位,基于视口宽度的百分比,1vw 等于视口宽度的 1%。
视口高度单位vh相对单位,基于视口高度的百分比,1vh 等于视口高度的 1%。
字体相对单位em相对单位,基于元素的字体大小。
根字体相对单位rem相对单位,基于根元素(:root 或 html)的字体大小。
非常小的设备xs用于小尺寸设备如手机竖屏。
小型设备sm用于稍大屏幕尺寸如手机横屏。
中等设备md用于中等屏幕设备如平板。
大型设备lg用于较大屏幕尺寸如桌面显示器。
非常大的设备xl用于非常大的屏幕尺寸,通常是大型桌面显示器。
超大的设备xxl在某些框架中使用,用于更大的桌面显示器。

Ubuntu 配置 zsh-syntax-highlighting 实现命令检查

· 阅读需 2 分钟
素明诚
Full stack development

安装 Zsh

确保你的系统上已经安装了 Zsh

# 对于 macOS
brew install zsh

# 对于 Ubuntu/Debian
sudo apt install zsh

# 对于 CentOS/RHEL
sudo yum install zsh

# 对于 Fedora
sudo dnf install zsh

设置 Zsh 为默认 Shell

将 Zsh 设置为默认的 Shell

chsh -s $(which zsh)

你可能需要退出并重新登录,或重启系统以应用更改。

安装 Oh My Zsh

Oh My Zsh 是一个流行的开源框架,用于管理你的 Zsh 配置。你可以通过以下命令来安装它

sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

安装 zsh-syntax-highlighting 插件

现在,你可以通过 git 克隆 zsh-syntax-highlighting 插件到 Oh My Zsh 的插件目录

git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting

配置 zsh-syntax-highlighting 插件

接下来,你需要配置 Oh My Zsh 以使用 zsh-syntax-highlighting 插件。通过编辑你的 ~/.zshrc 文件来完成这一步

nano ~/.zshrc

找到 plugins 这一行,并添加 zsh-syntax-highlighting

plugins=(git zsh-syntax-highlighting)

重点!确保 zsh-syntax-highlighting 在插件列表的最后一项,因为它需要在其他插件之后加载。

重新加载配置

保存并关闭 ~/.zshrc 文件,然后通过下面的命令来重新加载配置

source ~/.zshrc

配置成功效果如下

通过检查就是绿色

没有通过就是红色,可以帮助快速判断命令是否敲错了

9855560e682d68d3b5637adf63659054

如果您喜欢,希望能点赞支持一下

常见衡量指标和关键性能指标KPIs

· 阅读需 4 分钟
素明诚
Full stack development

基础性能指标

指标说明解释影响因素优化建议
QPS (Queries Per Second)每秒查询次数衡量系统每秒可以处理多少个查询请求。服务器硬件、数据库优化、应用程序效率优化 SQL 语句、增加缓存机制、提升服务器硬件
TPS (Transactions Per Second)每秒事务数衡量系统每秒可以处理多少个事务。事务复杂度、数据库锁定、并发处理能力使用更有效的事务处理策略、优化锁定机制
响应时间 (Response Time)响应时间衡量系统响应一个请求所需的时间。网络延迟、服务器处理能力、应用程序优化提升带宽、优化代码、升级服务器
吞吐量 (Throughput)吞吐量衡量单位时间内系统能处理的数据量。网络带宽、服务器性能、应用程序效率增强网络带宽、服务器扩容、应用程序优化
错误率 (Error Rate)错误率衡量请求总数中失败的比例。程序错误、系统超载、资源不足增强错误处理、优化资源分配、提升系统容错性

资源使用效率

指标说明解释影响因素优化建议
CPU 使用率 (CPU Utilization)CPU 使用率衡量 CPU 被使用的程度。应用程序效率、系统并发量、背景任务优化应用程序、合理安排后台任务、增加 CPU 资源
内存使用率 (Memory Utilization)内存使用率衡量系统内存使用情况。应用程序内存管理、系统负载优化内存使用、升级物理内存
磁盘 I/O (Disk I/O)磁盘输入输出操作衡量磁盘操作的速度和效率。磁盘性能、数据访问模式使用更快的磁盘、优化数据存储结构
网络 I/O (Network I/O)网络输入输出操作衡量网络传输数据的能力。网络设备性能、带宽限制升级网络设备、增加网络带宽

系统稳定性与可用性

指标说明解释影响因素优化建议
可用性 (Availability)系统可用性表示系统能够正常运行和服务的时间比例。硬件故障、软件错误、维护策略增加冗余系统、定期维护、使用高可用性设计
系统正常运行时间 (Uptime)系统正常运行时间系统连续运行不出故障的时间,通常以百分比表示,是衡量系统可靠性的重要指标。系统维护、硬件可靠性、软件稳定性优化维护流程、选择可靠硬件和软件
失败恢复时间 (Failover Time)故障切换时间系统在遇到硬件或软件故障时,恢复到正常运行状态所需的时间。故障检测速度、备用系统配置、故障响应策略部署快速故障检测机制、优化备用系统配置与故障响应时间
稳定性 (Stability)系统稳定性衡量系统在长时间运行或在高负载下的可靠性和稳定性。系统架构设计、负载管理、资源调度使用稳定的架构和高效的负载平衡技术、提前进行压力测试

高级性能指标

指标说明解释影响因素优化建议
页面加载时间 (Page Load Time)页面完全加载的时间表示从开始请求一个页面到页面完全加载完成所需的总时间。网络速度、服务器响应时间、页面内容大小优化内容传输、使用 CDN、压缩文件
首字节时间 (Time to First Byte - TTFB)首字节响应时间从用户发起请求到从服务器接收到第一个字节的时间。网络延迟、服务器处理能力提升服务器性能、优化网络结构
事务响应时间 (Transaction Response Time)事务响应时间完成一个事务所需的总时间。数据库效率、应用逻辑优化数据库访问、简化处理逻辑
请求等待时间 (Request Wait Time)请求等待处理的时间请求在队列中等待被处理的时间。服务器负载、资源调度策略资源优化分配、负载均衡

如果您喜欢这篇文章,不妨给它点个赞并收藏,感谢您的支持!