【Go】用Go在命令行输出好看的表格
用Go在命令行输出好看的表格
- 前言
- 正文
- 生成Table
- 表头设置
- 插入行
- 表格标题
- 自动标号
- 单元格合并
- 列合并
- 行合并
- 样式设置
- 居中设置
- 数字自动高亮标红
- 完整Demo代码
- 结语
前言
最近在写一些运维小工具,比如批量进行ping包的工具,实现不困难,反正就是ping,统计,然后输出,不过我本着自己既是开发者又是使用者的理念,还是不喜欢输出特别难看的工具,就像这样:

所以就去https://pkg.go.dev/瞄了一眼,看看有没有啥适合的库能够把输出整的好看点的,于是找到了一个库github.com/jedib0t/go-pretty/v6/table,这是一个在命令行输出格式化表格的库,这里记录一下使用这个库进行一些格式化输出的过程。
其实还有一个比较简单的库叫做gotable,也能实现基础的格式化输出功能,使用起来也方便些,不过功能相对来说就要单一一些,在表格样式设置上会差一些,没那么自由,也可以看下https://pkg.go.dev/github.com/liushuochen/gotable#section-readme
正文
接下来开始正式的去在命令行生成好看的满足需要的表格。
生成Table
首先我们要生成一个Table结构体的实例,可以直接New一个,也可以自己构造:
t := table.Table{}
// 或者
t := table.NewWriter()
NewWriter会返回一个Writer接口
表头设置
表格首先要设置表头,以我的应用为例,表头设置:
header := table.Row{"ID", "IP", "Num", "PacketsRecv", "PacketLoss", "AvgRtt"}
这样生成了一个表头行,然后要通过AppendHeader方法在表格中生效:
t.AppendHeader(header)
看看效果,表头已经打印出来了
+----+----+-----+-------------+------------+--------+
| ID | IP | NUM | PACKETSRECV | PACKETLOSS | AVGRTT |
+----+----+-----+-------------+------------+--------+
+----+----+-----+-------------+------------+--------+
插入行
数据的插入和表头的生成类似,要生成一个table.Row,然后调用AppendRow方法:
func (d *Demo) AppendRow() {for i := 1; i <= 5; i++ {row := table.Row{i, fmt.Sprintf("10.0.0.%v", i), i + 4, i, i, "AppendRow"}d.T.AppendRow(row)}
}
效果如下:
+----+----------+-----+-------------+------------+-----------+
| ID | IP | NUM | PACKETSRECV | PACKETLOSS | AVGRTT |
+----+----------+-----+-------------+------------+-----------+
| 1 | 10.0.0.1 | 5 | 1 | 1 | AppendRow |
| 2 | 10.0.0.2 | 6 | 2 | 2 | AppendRow |
| 3 | 10.0.0.3 | 7 | 3 | 3 | AppendRow |
| 4 | 10.0.0.4 | 8 | 4 | 4 | AppendRow |
| 5 | 10.0.0.5 | 9 | 5 | 5 | AppendRow |
+----+----------+-----+-------------+------------+-----------+
当然也可以生成table.Row的切片后调用一次AppendRows方法,效果和上面是一样的:
func (d *Demo) AppendRows() {var rows []table.Rowfor i := 1; i <= 5; i++ {rows = append(rows, table.Row{i, fmt.Sprintf("10.0.0.%v", i), i + 4, i, i, "AppendRows"})}d.T.AppendRows(rows)
}
+----+----------+-----+-------------+------------+------------+
| ID | IP | NUM | PACKETSRECV | PACKETLOSS | AVGRTT |
+----+----------+-----+-------------+------------+------------+
| 1 | 10.0.0.1 | 5 | 1 | 1 | AppendRow |
| 2 | 10.0.0.2 | 6 | 2 | 2 | AppendRow |
| 3 | 10.0.0.3 | 7 | 3 | 3 | AppendRow |
| 4 | 10.0.0.4 | 8 | 4 | 4 | AppendRow |
| 5 | 10.0.0.5 | 9 | 5 | 5 | AppendRow |
| 1 | 10.0.0.1 | 5 | 1 | 1 | AppendRows |
| 2 | 10.0.0.2 | 6 | 2 | 2 | AppendRows |
| 3 | 10.0.0.3 | 7 | 3 | 3 | AppendRows |
| 4 | 10.0.0.4 | 8 | 4 | 4 | AppendRows |
| 5 | 10.0.0.5 | 9 | 5 | 5 | AppendRows |
+----+----------+-----+-------------+------------+------------+
表格标题
在设置表格实际内容时,还可以设置一个表格标题,如下:
func (d *Demo) AddTitle() {d.T.SetTitle("This is Easy Table")
}
+-------------------------------------------------------------+
| This is Easy Table |
+----+----------+-----+-------------+------------+------------+
| ID | IP | NUM | PACKETSRECV | PACKETLOSS | AVGRTT |
+----+----------+-----+-------------+------------+------------+
| 1 | 10.0.0.1 | 5 | 1 | 1 | AppendRow |
| 2 | 10.0.0.2 | 6 | 2 | 2 | AppendRow |
| 1 | 10.0.0.1 | 5 | 1 | 1 | AppendRows |
| 2 | 10.0.0.2 | 6 | 2 | 2 | AppendRows |
+----+----------+-----+-------------+------------+------------+
自动标号
在插入行的时候,我额外输入了一个ID列,作为标号,其实table提供了相关的方法和接口,只需要调用SetAutoIndex方法,增加自动的索引列即可:
func (d *Demo) MakeHeader() {header := table.Row{"IP", "Num", "PacketsRecv", "PacketLoss", "AvgRtt"}d.T.AppendHeader(header)d.T.SetAutoIndex(true)
}
+------------------------------------------------------------+
| This is Easy Table |
+---+----------+-----+-------------+------------+------------+
| | IP | NUM | PACKETSRECV | PACKETLOSS | AVGRTT |
+---+----------+-----+-------------+------------+------------+
| 1 | 10.0.0.1 | 5 | 1 | 1 | AppendRow |
| 2 | 10.0.0.2 | 6 | 2 | 2 | AppendRow |
| 3 | 10.0.0.1 | 5 | 1 | 1 | AppendRows |
| 4 | 10.0.0.2 | 6 | 2 | 2 | AppendRows |
+---+----------+-----+-------------+------------+------------+
单元格合并
有的时候,相邻单元格的值一样我们可能会想要进行合并,这样更美观,单元格合并分为列合并和行合并;先定义一下这里的列合并和行合并:
- 列合并:针对单列,如果单列中的多个相邻行数据一样,那么就合并为一个大行;
- 行合并:针对单行,如果单行中的多个相邻列数据一样,那么久合并为一个大列;
这里我们用到的原始表格如下:
+--------------------------------------------------------------+
| This is Easy Table |
+---+----------+-------+-------------+------------+------------+
| | IP | NUM | PACKETSRECV | PACKETLOSS | AVGRTT |
+---+----------+-------+-------------+------------+------------+
| 1 | 10.0.0.1 | 5 | 1 | 1 | AppendRow |
| 2 | 10.0.0.2 | 6 | 2 | 2 | AppendRow |
| 3 | 10.0.0.1 | 5 | 1 | 1 | AppendRows |
| 4 | 10.0.0.2 | 6 | 2 | 2 | AppendRows |
+---+----------+-------+-------------+------------+------------+
| | TOTAL | TOTAL | TOTAL | TOTAL | 4 |
+---+----------+-------+-------------+------------+------------+
列合并
我们先进行最后一列AvgRtt的列合并:
func (d *Demo) ColumnMerge() {d.T.SetColumnConfigs([]table.ColumnConfig{{Name: "AvgRtt",// Number是指定列的序号// Number: 5,AutoMerge: true,Align: text.AlignCenter,},})
}
可以选择通过列的表头或者列的序号来选择具体进行合并的列:
+---+----------+-------+-------------+------------+------------+
| | IP | NUM | PACKETSRECV | PACKETLOSS | AVGRTT |
+---+----------+-------+-------------+------------+------------+
| 1 | 10.0.0.1 | 5 | 1 | 1 | AppendRow |
| 2 | 10.0.0.2 | 6 | 2 | 2 | |
| 3 | 10.0.0.1 | 5 | 1 | 1 | AppendRows |
| 4 | 10.0.0.2 | 6 | 2 | 2 | |
+---+----------+-------+-------------+------------+------------+
| | TOTAL | TOTAL | TOTAL | TOTAL | 4 |
+---+----------+-------+-------------+------------+------------+
这样看表格线条不明显,感觉不到区分,那么可以加上一些设置
d.T.Style().Options.SeparateRows = true
+---+----------+-------+-------------+------------+------------+
| | IP | NUM | PACKETSRECV | PACKETLOSS | AVGRTT |
+---+----------+-------+-------------+------------+------------+
| 1 | 10.0.0.1 | 5 | 1 | 1 | AppendRow |
+---+----------+-------+-------------+------------+ |
| 2 | 10.0.0.2 | 6 | 2 | 2 | |
+---+----------+-------+-------------+------------+------------+
| 3 | 10.0.0.1 | 5 | 1 | 1 | AppendRows |
+---+----------+-------+-------------+------------+ |
| 4 | 10.0.0.2 | 6 | 2 | 2 | |
+---+----------+-------+-------------+------------+------------+
| | TOTAL | TOTAL | TOTAL | TOTAL | 4 |
+---+----------+-------+-------------+------------+------------+
行合并
行合并我们对最后一行的汇总行进行合并,具体做法是在添加汇总行时增加RowConfig参数:
func (d *Demo) AppendFooter() {d.T.AppendFooter(table.Row{"Total", "Total", "Total", "Total", count}, table.RowConfig{AutoMerge: true})
}
+---+----------+-------+-------------+------------+------------+
| | IP | NUM | PACKETSRECV | PACKETLOSS | AVGRTT |
+---+----------+-------+-------------+------------+------------+
| 1 | 10.0.0.1 | 5 | 1 | 1 | AppendRow |
+---+----------+-------+-------------+------------+ |
| 2 | 10.0.0.2 | 6 | 2 | 2 | |
+---+----------+-------+-------------+------------+------------+
| 3 | 10.0.0.1 | 5 | 1 | 1 | AppendRows |
+---+----------+-------+-------------+------------+ |
| 4 | 10.0.0.2 | 6 | 2 | 2 | |
+---+----------+-------+-------------+------------+------------+
| | TOTAL | 4 |
+---+---------------------------------------------+------------+
样式设置
现在整个表格已经生成,但我们还需要进行一些美化,这就要对表格的样式进行设置了;
居中设置
对于居中,无法直接进行全局的设置,必须根据列进行,如下:
func (d *Demo) SetAlignCenter() {column := []string{"IP", "Num", "PacketsRecv", "PacketLoss", "AvgRtt"}c := []table.ColumnConfig{}// 根据表格的列数循环进行设置,统一居中for i := 1; i <= len(column); i++ {name := column[i-1]if name == "AvgRtt" {c = append(c, table.ColumnConfig{Name: "AvgRtt",AutoMerge: true,Align: text.AlignCenter,AlignHeader: text.AlignCenter,AlignFooter: text.AlignCenter,})continue}c = append(c, table.ColumnConfig{Name: column[i],Align: text.AlignCenter,AlignHeader: text.AlignCenter,AlignFooter: text.AlignCenter,})}d.T.SetColumnConfigs(c)
}
居中效果如下,这样既能保留列合并又完成了剧中设置:
+---+----------+-------+-------------+------------+------------+
| | IP | NUM | PACKETSRECV | PACKETLOSS | AVGRTT |
+---+----------+-------+-------------+------------+------------+
| 1 | 10.0.0.1 | 5 | 1 | 1 | AppendRow |
+---+----------+-------+-------------+------------+ |
| 2 | 10.0.0.2 | 6 | 2 | 2 | |
+---+----------+-------+-------------+------------+------------+
| 3 | 10.0.0.1 | 5 | 1 | 1 | AppendRows |
+---+----------+-------+-------------+------------+ |
| 4 | 10.0.0.2 | 6 | 2 | 2 | |
+---+----------+-------+-------------+------------+------------+
| | TOTAL | 4 |
+---+---------------------------------------------+------------+
数字自动高亮标红
在我的应用场景中,ping的ip如果出现了丢包情况,那就要红色高亮,方便使用者马上关注到,这种情况下,可以通过Transformer来设置:
func (d *Demo) SetWarnColor() {// 字体颜色WarnColor := text.Colors{text.BgRed}warnTransformer := text.Transformer(func(val interface{}) string {if val.(float64) > 0 {// 统计丢包服务器总数return WarnColor.Sprintf("%.2f%%", val)}return fmt.Sprintf("%v%%", val)})d.T.SetColumnConfigs([]table.ColumnConfig{{Name: "PacketLoss",AutoMerge: true,Align: text.AlignCenter,AlignHeader: text.AlignCenter,AlignFooter: text.AlignCenter,Transformer: warnTransformer,},})
}
实际效果如下:

完整Demo代码
package mainimport ("fmt""math/rand""github.com/jedib0t/go-pretty/v6/table""github.com/jedib0t/go-pretty/v6/text"
)var count = 0type Demo struct {T table.Writer
}func NewDemo() *Demo {return &Demo{T: table.NewWriter(),}
}func (d *Demo) MakeHeader() {header := table.Row{"IP", "Num", "PacketsRecv", "PacketLoss", "AvgRtt"}d.T.AppendHeader(header)d.T.SetAutoIndex(true)// d.T.SetStyle(table.StyleLight)d.T.Style().Options.SeparateRows = true
}func (d *Demo) AddTitle() {d.T.SetTitle("This is Easy Table")
}func (d *Demo) AppendRow() {// rowConfig := table.RowConfig{AutoMerge: true}for i := 1; i <= 2; i++ {row := table.Row{fmt.Sprintf("10.0.0.%v", i), i + 4, i, rand.Float64() * 100, "AppendRow"}count += 1d.T.AppendRow(row)}d.T.AppendRow(table.Row{fmt.Sprintf("10.0.0.%v", 4), 1 + 4, 1, 0.0, "AppendRow"})
}func (d *Demo) AppendRows() {var rows []table.Rowfor i := 1; i <= 2; i++ {rows = append(rows, table.Row{fmt.Sprintf("10.0.0.%v", i), i + 4, i, rand.Float64() * 100, "AppendRows"})count += 1}d.T.AppendRows(rows)
}func (d *Demo) AppendFooter() {d.T.AppendFooter(table.Row{"Total", "Total", "Total", "Total", count}, table.RowConfig{AutoMerge: true, AutoMergeAlign: text.AlignCenter})
}func (d *Demo) ColumnMerge() {d.T.SetColumnConfigs([]table.ColumnConfig{{Name: "AvgRtt",// Number是指定列的序号// Number: 5,AutoMerge: true,Align: text.AlignCenter,},})
}func (d *Demo) SetAlignCenter() {column := []string{"IP", "Num", "PacketsRecv", "PacketLoss", "AvgRtt"}c := []table.ColumnConfig{}// 根据表格的列数循环进行设置,统一居中for i := 1; i <= len(column); i++ {name := column[i-1]if name == "AvgRtt" {c = append(c, table.ColumnConfig{Name: "AvgRtt",AutoMerge: true,Align: text.AlignCenter,AlignHeader: text.AlignCenter,AlignFooter: text.AlignCenter,})continue}c = append(c, table.ColumnConfig{Name: column[i],Align: text.AlignCenter,AlignHeader: text.AlignCenter,AlignFooter: text.AlignCenter,})}d.T.SetColumnConfigs(c)
}func (d *Demo) SetWarnColor() {// 字体颜色WarnColor := text.Colors{text.BgRed}warnTransformer := text.Transformer(func(val interface{}) string {if val.(float64) > 0 {// 统计丢包服务器总数return WarnColor.Sprintf("%.2f%%", val)}return fmt.Sprintf("%v%%", val)})d.T.SetColumnConfigs([]table.ColumnConfig{{Name: "PacketLoss",AutoMerge: true,Align: text.AlignCenter,AlignHeader: text.AlignCenter,AlignFooter: text.AlignCenter,Transformer: warnTransformer,},})
}func (d *Demo) Print() {fmt.Println(d.T.Render())
}func main() {demo := NewDemo()demo.MakeHeader()// demo.AddTitle()demo.AppendRow()demo.AppendRows()// demo.ColumnMerge()demo.AppendFooter()// demo.SetAlignCenter()demo.SetWarnColor()demo.Print()
}
结语
本文介绍了使用第三方库美化Golang的命令行表格格式化输出,除了table以外,go-pretty库中还包含了进度条、列表等美化方法,感兴趣可以自己看看官方文档。
相关文章:
【Go】用Go在命令行输出好看的表格
用Go在命令行输出好看的表格前言正文生成Table表头设置插入行表格标题自动标号单元格合并列合并行合并样式设置居中设置数字自动高亮标红完整Demo代码结语前言 最近在写一些运维小工具,比如批量进行ping包的工具,实现不困难,反正就是ping&am…...
怎么处理消息重发的问题?
消息队列在消息传递的过程中,如果出现传递失败的情况,发送方会重试,在重试的过程中,可能会产生重复的消息。 消息重复的情况必然存在 关于传递消息时能够提供的服务质量标准,MQTT协议给出了三种不同的标准࿱…...
JVM 运行时数据区(数据区组成表述,程序计数器,java虚拟机栈,本地方法栈)
JVM 运行时数据区JVM 运行时数据区3.1运行时的数据区组成概述3.1.1程度计数器3.1.2java虚拟机栈3.1.3本地方法栈3.1.4java堆3.1.5方法区3.2程序计数器3.3java虚拟机栈3.4本地方法栈JVM 运行时数据区 堆,方法区(元空间) 主要用来存放数据 是线程共享的. 程序计数器,本地方法栈…...
Oracle ASM磁盘组配置、日常运维、故障处理等操作资料汇总
ASM(自动存储管理)在数据库中是非常重要的组成部分,它可以为磁盘提供统一的存储管理、提高磁盘访问的性能和可用性、简化管理复杂度,从而为数据库的运行提供更好的支持。这里就为大家整理了墨天轮数据社区上一些ASM相关基础知识、…...
java对象的创建与内存分配机制
文章目录对象的创建与内存分配机制对象的创建类加载检查分配内存初始化零值设置对象头指向init方法其他:指针压缩对象内存分配对象在栈上分配对象在Eden区中分配大对象直接分配到老年代长期存活的对象进入老年代对象动态年龄判断老年代空间分配担保机制对象的内存回…...
本地存储localStorage、sessionStorage
目录 一、localStorage 二、sessionStorage 三、本地存储处理复杂数据 一、localStorage 介绍 (1)数据存储在用户浏览器中 (2)设置、读取方便、甚至页面刷新不会丢失数据 (3)容量较大,se…...
JavaSE: 网络编程
1.1 概述java程序员面对统一的网络编程环境B/S 架构 和 C/S架构1.2 网络通信的两个要素通信双方的地址:ip 端口号网络通信协议:TCP/IP协议(事实上的国际规则)、OSI模型(理想化)1.3 Inet Address本地回环地…...
计算机图形学09:二维观察之点的裁剪
作者:非妃是公主 专栏:《计算机图形学》 博客地址:https://blog.csdn.net/myf_666 个性签:顺境不惰,逆境不馁,以心制境,万事可成。——曾国藩 文章目录专栏推荐专栏系列文章序一、二维观察基本…...
2023Java 并发编程面试题
Java 并发编程 1、在 java 中守护线程和本地线程区别? java 中的线程分为两种:守护线程(Daemon)和用户线程(User)。任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon(boolon…...
CAD如何绘制A0/A1/A2/A3/A4图框?
在CAD制图时,设计师一般会使用企业的定制图框模板或者个人的特色图框模板,让设计方案更加标准化、规范化。对于新人设计师而言,完成CAD制图已经非常头疼了,图框的绘制更是手忙脚乱。那么是否有更加高效的方式来完成A0、A1、A2、A3…...
R 安装 “umap-learn“ python 包
首先需要在R中下载并读取reticulate包,该包提供了一系列R-Python的交互式命令由于之前在电脑中通过三个方式安装了Python:直接安装 Python 3.10安装Anaconda,携带3.9安装 Miniconda,又是另外一个版本的Python版本各不相同…...
测试同学如何快速开发测试平台?
转眼已经好几个月没有发表什么文章了,因为疫情原因,大家工作都不怎么顺利,没有什么心情。再者,最近一直在搞移动端精准测试的项目,有太多技术难点需要攻克。从各个网站上都找不到解决方案,只能不断地尝试&a…...
【程序员接口百宝箱】免费常用API接口
一、短信发送 短信的应用可以说是非常的广泛了,短信API也是当下非常热门的API~ 短信验证码:可用于登录、注册、找回密码、支付认证等等应用场景。支持三大运营商,3秒可达,99.99%到达率,支持大容量高并发。…...
使数组和能被P整除[同余定理+同余定理变形]
同余定理同余定理变形前言一、使数组和能被P整除二、同余定理变形总结参考资料前言 同余定理非常经典,采用前缀和 map,当两个余数前缀和为一个值时,则中间一段子数组刚好对P整除。但是能否找到前面是否有一段子数组和可以对P整除呐…...
25k的Java开发常问的Synchronized问题有哪些?
前言:面试高频的Synchronized问题大多集中在应用场景、底层实现原理、锁的升级过程。 文章目录 Synchronized定义应用场景对象加锁实现原理JDK6以前JDK6版本及以后对象从无锁到偏向锁转化的过程(大概讲五分钟)轻量级锁升级的过程(大概讲五分钟)自旋锁策略(大概讲五分钟)…...
ES增量同步方案
1 基于业务代码嵌入式的增量同步方式在Java业务代码要修改业务数据的地方,增加调用写入ES数据的方法优点:1、实现方式简单,可控粒度高;2、不依赖第三方数据同步框架;3、数据库不用做特殊配置和部署;缺点&am…...
计算器--课后程序(Python程序开发案例教程-黑马程序员编著-第6章-课后作业)
实例1:计算器 计算器极大地提高了人们进行数字计算的效率与准确性,无论是超市的收银台,还是集市的小摊位,都能够看到计算器的身影。计算器最基本的功能是四则运算。本实例要求编写程序,实现计算器的四则运算功能。 实…...
YOLOv5中添加SE模块详解——原理+代码
目录一、SENet1. 设计原理2. SE Block2.1 Squeeze:Global Information Embedding2.2 Excitation:Adaptive Recalibration3. SE-Inception and SE-ResNet二、YOLOv5中添加SENet1.修改common.py2.修改yolo.py3.修改yolov5s.yaml参考文章一、SENet 论文地址:Squeeze-a…...
arcgispro3.1(账号登陆)
ArcGIS Pro 3.1 更新中文概览专注于 制图、GIS、Python前言:本次更新给了我两个惊喜,一个是本来 ArcMap 就有的功能,另一个明显是学习的 QGIS,嘿嘿,大家往下看吧。整理翻译了一下官方的 ArcGIS Pro 3.1 新特性更新概览…...
VB6换个思路解决微信下载文件只读的问题(含源码)
日期:2023年3月10日 作者:Commas 签名:(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释:如果您觉得有所帮助,帮忙点个赞,也可以关注我,我们一起成长;如果有不对的地方…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
