Go语言入门
文章目录
- 零、Linux下Go的安装
- 1.下载、解压
- 2.添加环境变量
- 3.验证安装
- 4.初始化Go模块
- (1)cd到项目目录
- (2)初始化模块
- (3)获取依赖包
- (4)清理和验证依赖
- (5)检查 go.mod 文件
- (6)介绍 go.mod 和 go.sum 文件
- 5.项目目录结构
- 一、感性认识
- 1.从 Hello world 开始
- 2.加法函数
- 二、Go语法
- 1.变量的声明与初始化
- (1):=:自动推断类型
- (2)var:手动指定类型
- 2.基础数据类型
- (1)布尔型(Boolean)
- (2)整型(Integer)
- (3)浮点型(Floating-point)
- (4)复数类型(Complex)
- (5)字符串(String)
- 3.变量、常量
- (1)变量
- (2)常量
- 4.控制结构
- (1)条件语句
- (2)循环语句
- ①for循环
- ②range 循环:用于遍历数组、切片、字符串、map 等数据结构
- 5.函数
- 三、Go的数据结构
- (一) 内置数据结构
- 1.数组 (Array)
- 2.切片 (Slice)
- 3.映射 (Map)
- 4.结构体 (Struct)
- 5.指针 (Pointer)
- (二) Go库提供的数据结构
- 1.container/list:双向链表
- 2.container/heap:堆/优先队列
- 3.container/ring:环形链表
- 四、Go的三种编译方式
- 1.go run
- 2.go build
- 3.go install
- 五、Go与C++混合编程
- 1.原理
- 2.步骤
- 六、termui
- 1.官网
- 2.代码及效果
- (1)HelloWorld框
- (2)彩色文字框
- (3)实时数据动态变化
- (4)折线图、打印系统信息
零、Linux下Go的安装
1.下载、解压
wget https://golang.org/dl/go1.20.5.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.20.5.linux-amd64.tar.gz
2.添加环境变量
(1)编辑 shell 配置文件
vim ~/.bashrc
(2)写入以下内容
export GOPATH=$HOME/go
export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin
(3)运行一下
source ~/.bashrc
3.验证安装
go version
示例输出:
go version go1.20.4 linux/amd64
4.初始化Go模块
(1)cd到项目目录
确保你在包含 ui.go 文件的项目根目录下。例如:
cd ~/termui
(2)初始化模块
使用 go mod init 命令初始化模块,并指定模块路径。模块路径通常是你的代码仓库地址,但对于本地项目,你可以使用任意名称。
go mod init mytermui
注意:将 mytermui 替换为你项目的实际模块名。如果你有特定的仓库地址,可以使用类似 github.com/你的用户名/项目名 的格式。
go mod init github.com/yourusername/mytermui
这将在当前目录下创建一个 go.mod 文件,内容类似于:
module github.com/yourusername/mytermuigo 1.20
(3)获取依赖包
使用 go get 命令获取 termui/v3 包及其依赖:
go get github.com/gizak/termui/v3@latest
这将下载 termui 的最新版本,并更新 go.mod 和 go.sum 文件。
(4)清理和验证依赖
运行以下命令以确保所有依赖都已正确安装:
go mod tidy
这个命令会清理 go.mod 和 go.sum 文件,移除未使用的依赖并添加缺失的依赖。
(5)检查 go.mod 文件
确保 go.mod 文件中正确记录了 termui 依赖。例如:
module github.com/yourusername/mytermuigo 1.20require github.com/gizak/termui/v3 v3.1.0 // 具体版本可能不同
(6)介绍 go.mod 和 go.sum 文件
(1)go.mod
文件
go.mod文件用于定义当前 Go 项目的模块信息,包括模块的路径、Go 语言的版本以及项目所依赖的其他模块及其版本。它是 Go Modules 的核心配置文件,确保项目依赖的一致性和可重复构建。
module github.com/yourusername/yourprojectgo 1.20require (github.com/gizak/termui/v3 v3.1.0github.com/sirupsen/logrus v1.8.1
)
(2)go.sum
文件
go.sum文件用于记录项目所依赖的每个模块及其具体版本的 校验和(checksum)。它确保在不同时间和不同环境中下载的依赖包内容一致,防止依赖包被篡改或出现版本不一致的问题,从而提高项目构建的安全性和可靠性。
github.com/gizak/termui/v3 v3.1.0 h1:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
github.com/gizak/termui/v3 v3.1.0/go.mod h1:yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
github.com/sirupsen/logrus v1.8.1 h1:zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
github.com/sirupsen/logrus v1.8.1/go.mod h1:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
5.项目目录结构
termui/ # 项目根目录
├── go.mod # 模块定义文件
├── go.sum # 依赖校验文件
└── ui.go # 你的主程序文件
一、感性认识
1.从 Hello world 开始
1.代码
package mainimport "fmt"func main() {fmt.Println("Hello, World!")
}
fmt 是 Go 标准库中的一个包,提供了格式化I/O功能。它包含了用于格式化文本和实现基本输入输出的函数,可以方便地处理字符串、数字等类型的格式化打印以及解析。
2.运行
go run hello.go
2.加法函数
1.代码
package mainimport "fmt"// add 函数接收两个整数参数,并返回它们的和
func add(a int, b int) int {return a + b
}func main() {sum := add(5, 3)fmt.Printf("5 + 3 = %d\n", sum)
}
2.运行
go run add.go
二、Go语法
1.变量的声明与初始化
(1):=:自动推断类型
1.概念
:=
允许你在声明变量的同时进行初始化,并且无需显式指定变量的类型。Go 编译器会根据赋值的值自动推断变量的类型。
2.使用范围:函数内部
:=
只能在函数内部使用,不能用于包级别的变量声明。而var可以在函数内部和包级别使用
3.代码
package mainimport "fmt"func main() {// 使用 := 声明并初始化变量message := "Hello, Go!"count := 10pi := 3.14fmt.Println(message)fmt.Println("Count:", count)fmt.Println("Pi:", pi)
}
(2)var:手动指定类型
1.举例
var count int = 10
2.适用范围:包级别、函数内部
package mainimport "fmt"// 包级别变量声明,必须使用 var
var globalMessage = "Hello from package level!"func main() {fmt.Println(globalMessage)
}
2.基础数据类型
(1)布尔型(Boolean)
var isReady bool = true
fmt.Println(isReady) // 输出: true
(2)整型(Integer)
1.有符号整型
int, int8, int16, int32, int64
范围:
int8:-128 ~ 127
int16:-32,768 ~ 32,767
int32:-2,147,483,648 ~ 2,147,483,647
int64:-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
int:与系统架构相关,通常为 int32 或 int64
2.无符号整型
类型:uint, uint8, uint16, uint32, uint64
范围:
uint8(等同于字节 byte):0 ~ 255
uint16:0 ~ 65,535
uint32:0 ~ 4,294,967,295
uint64:0 ~ 18,446,744,073,709,551,615
uint:与系统架构相关
var a int = 100
var b uint8 = 255
fmt.Println(a, b) // 输出: 100 255
(3)浮点型(Floating-point)
类型:float32, float64
精度:
float32:约 6-7 位小数精度
float64:约 15-16 位小数精度
var pi float64 = 3.141592653589793
fmt.Println(pi) // 输出: 3.141592653589793
(4)复数类型(Complex)
类型:complex64, complex128
组成:
complex64:由两个 float32 组成
complex128:由两个 float64 组成
var c complex128 = 1 + 2i
fmt.Println(c) // 输出: (1+2i)
fmt.Println(real(c)) // 输出: 1
fmt.Println(imag(c)) // 输出: 2
(5)字符串(String)
类型:string
特点:字符串是不可变的,存储 UTF-8 编码的字节序列。
var s string = "Hello, 世界"
fmt.Println(s) // 输出: Hello, 世界
fmt.Println(len(s)) // 输出: 13(一个汉字占3字节)
3.变量、常量
(1)变量
1.使用 var 关键字
var 变量名 数据类型 = 初始值
var a int = 10
var b string = "hello"
var c bool = true
2.省略数据类型(自动推导类型)
var 变量名 = 初始值
var x = 3.14 // 自动推导为 float64
var y = "Go" // 自动推导为 string
3.简短声明(仅限函数内部)
变量名 := 初始值
z := 42 // 自动推导为 int
message := "Welcome to Go"
(2)常量
常量:用const关键字修饰
const 常量名 数据类型 = 值
const pi float64 = 3.14159
const language = "Go"
4.控制结构
(1)条件语句
package mainimport "fmt"func main(){var age int = 25fmt.Println("age = ", age)if age < 18{fmt.Println("未成年")}else if age <= 30{fmt.Println("青年")}else if age <= 60{fmt.Println("中年")}else{fmt.Println("老年")}
}
(2)循环语句
①for循环
1.Go 语言的循环控制结构非常简洁,它只有一种循环结构:for 循环。
for 初始语句; 条件语句; 后续语句 {// 循环体代码
}
2.也可以省略 初始语句 和 后续语句,只保留 条件语句,这种形式相当于其他语言中的 while 循环。
for 条件语句 {// 循环体代码
}
3.也可以写一个无限循环,通常在某些特定条件下需要手动跳出循环。Go 语言通过 for 语句支持无限循环。
for {// 无限循环体
}
②range 循环:用于遍历数组、切片、字符串、map 等数据结构
range 循环:Go 语言还提供了 range 关键字,可以在循环中迭代数组、切片、字符串、map 或通道等集合类型。
5.函数
进行函数封装
package mainimport "fmt"func printBool(b bool){fmt.Println(b)
}func printInts(a int, b uint8){fmt.Println(a, b)
}func printFloat(f float64){fmt.Println(f)
}func printComplex(c complex128){fmt.Println(c);fmt.Println(real(c))fmt.Println(imag(c))
}func printString(s string){fmt.Println(s)fmt.Println(len(s))
}func main(){var isReady bool = truevar a int = 100var b uint8 = 255var pi float64 = 3.14159265358979var c complex128 = 1 + 2ivar s string = "Hello, 世界"printBool(isReady)printInts(a, b)printFloat(pi)printComplex(c)printString(s)
}
三、Go的数据结构
(一) 内置数据结构
1.数组 (Array)
数组是具有固定长度且元素类型相同的序列。在 Go 中,数组的长度是类型的一部分,这意味着 [5]int 和 [10]int 是不同的类型。
特点:
固定长度,编译时确定。
值类型,数组赋值会复制所有元素。
package mainimport "fmt"func main() {var arr [3]intarr[0] = 10arr[1] = 20arr[2] = 30fmt.Println(arr) // 输出: [10 20 30]fmt.Println(len(arr)) // 输出: 3
}
2.切片 (Slice)
切片是对数组的一个动态窗口,具有可变长度和容量。切片是 Go 中使用最广泛的数据结构之一。
特点:
动态大小,基于底层数组实现。
引用类型,切片之间共享底层数组。
内置的 append 函数用于添加元素
package mainimport "fmt"func main() {// 创建切片s := []int{1, 2, 3, 4, 5}fmt.Println(s) // 输出: [1 2 3 4 5]fmt.Println(len(s)) // 输出: 5fmt.Println(cap(s)) // 输出: 5// 添加元素s = append(s, 6)fmt.Println(s) // 输出: [1 2 3 4 5 6]fmt.Println(len(s)) // 输出: 6fmt.Println(cap(s)) // 根据内存情况,可能增加到10// 切片的截取sub := s[1:4]fmt.Println(sub) // 输出: [2 3 4]
}
3.映射 (Map)
映射是一种键值对(key-value)的无序集合,类似于其他语言中的哈希表或字典。
特点:
无序,基于哈希实现。
键必须是可比较的类型(如字符串、整数、指针等)。
动态大小。
package mainimport "fmt"func main() {// 创建映射m := make(map[string]int)// 添加键值对m["Alice"] = 25m["Bob"] = 30// 访问元素fmt.Println(m["Alice"]) // 输出: 25// 检查键是否存在age, exists := m["Charlie"]if exists {fmt.Println(age)} else {fmt.Println("Charlie 不存在")}// 删除键值对delete(m, "Bob")fmt.Println(m) // 输出: map[Alice:25]
}
4.结构体 (Struct)
结构体是由一组字段组成的复合数据类型,类似于其他语言中的类或记录。
特点:
支持嵌套和匿名字段。
可以组合不同类型的数据。
package mainimport "fmt"// 定义结构体
type Person struct {Name stringAge int
}func main() {// 创建结构体实例p := Person{Name: "Alice", Age: 30}fmt.Println(p) // 输出: {Alice 30}// 访问字段fmt.Println(p.Name) // 输出: Alicefmt.Println(p.Age) // 输出: 30// 修改字段p.Age = 31fmt.Println(p.Age) // 输出: 31
}
5.指针 (Pointer)
指针存储变量的内存地址,允许直接操作内存中的数据。
指针类型以 * 表示。
允许在函数间传递引用,避免复制大量数据。
package mainimport "fmt"func main() {var a int = 10var p *int = &afmt.Println(p) // 输出: 内存地址,如 0xc0000140b8fmt.Println(*p) // 输出: 10*p = 20fmt.Println(a) // 输出: 20
}
(二) Go库提供的数据结构
1.container/list:双向链表
package mainimport ("container/list""fmt"
)func main() {l := list.New()l.PushBack("Go")l.PushBack("is")l.PushBack("awesome")for e := l.Front(); e != nil; e = e.Next() {fmt.Println(e.Value)}
}
2.container/heap:堆/优先队列
package mainimport ("container/heap""fmt"
)// IntHeap 是一个最小堆
type IntHeap []intfunc (h IntHeap) Len() int { return len(h) }
func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h IntHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }func (h *IntHeap) Push(x interface{}) {*h = append(*h, x.(int))
}func (h *IntHeap) Pop() interface{} {old := *hn := len(old)x := old[n-1]*h = old[0 : n-1]return x
}func main() {h := &IntHeap{5, 3, 2, 4}heap.Init(h)heap.Push(h, 1)fmt.Printf("最小值: %d\n", (*h)[0])for h.Len() > 0 {fmt.Printf("%d ", heap.Pop(h))}// 输出: 最小值: 1// 1 2 3 4 5
}
3.container/ring:环形链表
package mainimport ("container/ring""fmt"
)func main() {r := ring.New(5)for i := 0; i < r.Len(); i++ {r.Value = ir = r.Next()}r.Do(func(x interface{}) {fmt.Println(x)})
}
四、Go的三种编译方式
Go 语言是静态编译型语言,确实需要编译。与一些解释型语言不同,Go 源代码在执行之前必须先通过编译器转换成机器码,生成可以直接由计算机硬件执行的二进制文件。编译过程会检查代码中的语法错误和其他编译时错误,并将源代码优化为高效的机器码。
Go 提供了简单的工具链来管理和编译项目,主要的编译命令包括:go run、go build、go install。
当你编写 Go 应用程序时,你确实需要使用这些命令之一来编译你的代码。不过,Go 的编译速度非常快,这得益于其设计和实现,使得开发体验更加流畅,有时候甚至让人感觉像是在使用解释型语言。
总结来说,Go 语言不仅需要编译,而且它有着高效的编译工具链,让开发者可以快速地从编写代码到运行程序。
1.go run
编译并立即运行指定的 Go 文件,不会留下编译后的二进制文件
2.go build
go build:编译当前包或指定的 Go 文件。如果包含 package main 和 main 函数,则会生成一个可执行文件。
3.go install
go install:类似于 go build,但它还会将生成的二进制文件复制到 $GOPATH/bin 或 $GOBIN 环境变量所指定的目录中,使得可以从任何地方运行该程序。
五、Go与C++混合编程
1.原理
Go 提供了 cgo
工具,允许 Go 代码调用 C 函数。
由于 C++ 与 C 兼容性较高,通过 extern "C"
使 Go 调用 C++ 函数。
链接机制:将 C++ 代码编译为静态库(如 .a 或 .lib),然后在 Go 中链接使用。
2.步骤
1.创建头文件 (hello.h)
为了让 cgo 正确识别并调用 C++ 函数,建议创建一个头文件 hello.h,其中声明了 HelloWorld 函数
#ifndef HELLO_H
#define HELLO_H#ifdef __cplusplus
extern "C" {
#endifvoid HelloWorld();#ifdef __cplusplus
}
#endif#endif // HELLO_H
2.编写 C++ 源文件 (hello.cpp)
#include <iostream>
#include "hello.h"using std::cout;
using std::endl;extern "C" void HelloWorld(){cout << "Hello World from C++!" << endl;cout << "Just for test!" << endl;cout << "Cpp with GO!" << endl;
}
3.编写 Go 代码 (main.go)
在 main.go 中使用 cgo 调用 C++ 的 HelloWorld 函数
注意:Go中的这段注释是必要的,指明了链接器。
注意:注释块要和import "C"是连着的,不能空行。否则 go build -o main main.go 会报错 could not determine kind of name for C.HelloWorld
package main/*
#cgo CXXFLAGS: -std=c++11
#cgo LDFLAGS: -L. -lhello -lstdc++
#include "hello.h"
*/
import "C"func main() {C.HelloWorld()
}
4.编译 C++ 代码为目标文件
将 hello.cpp 编译为目标文件 hello.o。
g++ -c hello.cpp -o hello.o
-c:只编译,不链接
-o:指定输出文件名
在本例中,hello.o 是指定的目标文件名。如果不使用 -o 选项,默认情况下编译器会给目标文件命名为源文件名去掉扩展名再加上 .o 扩展名
5.创建静态库.a
将目标文件打包成静态库 libhello.a
ar rcs libhello.a hello.o
ar:GNU 的归档工具,用于创建、修改和提取静态库 (.a 文件)
rcs:选项。
①r选项:告诉 ar 将指定的目标文件插入到静态库中。如果静态库不存在,则会创建它;如果静态库已经存在,并且其中已有同名的目标文件,那么该选项将替换旧的目标文件。
②c选项:表示如果静态库尚不存在,则创建一个新的静态库。当与 r 一起使用时,确保即使静态库不存在也会被创建。
③s选项:指示 ar 为静态库创建索引。这个索引可以帮助链接器更快地找到库中的符号。这对于大型库来说尤其有用,因为它可以加速链接过程。
6.编译 Go 代码
go build -o main main.go
go官方文档推荐的顺序:go build -o output_filename source_files…
若go build 源文件名,不加-o 输出文件名。则会输出源文件名.go
中的源文件名。例如 go build main.go输出的可执行程序就是main。
7.运行Go程序
./main
8.预期输出
Hello World from C++!
六、termui
1.官网
termui是Go语言的终端ui
官网库:https://github.com/gizak/termui
2.代码及效果
(1)HelloWorld框
package mainimport ("log"ui "github.com/gizak/termui/v3""github.com/gizak/termui/v3/widgets"
)func main() {if err := ui.Init(); err != nil {log.Fatalf("failed to initialize termui: %v", err)}defer ui.Close()p := widgets.NewParagraph()p.Text = "Hello World!"p.SetRect(0, 0, 25, 5)ui.Render(p)for e := range ui.PollEvents() {if e.Type == ui.KeyboardEvent {break}}
}
(2)彩色文字框
package mainimport (ui "github.com/gizak/termui/v3""github.com/gizak/termui/v3/widgets""log"
)func main() {if err := ui.Init(); err != nil {log.Fatalf("failed to initialize termui: %v", err)}defer ui.Close()// 创建一个新的段落(Paragraph)组件p := widgets.NewParagraph()p.Text = "Press q to quit demo"p.SetRect(0, 0, 50, 3) // 设置位置和大小p.TextStyle.Fg = ui.ColorWhitep.Border = truep.BorderStyle.Fg = ui.ColorCyanp.Title = "Text Box"ui.Render(p)// 事件循环uiEvents := ui.PollEvents()for {e := <-uiEventsif e.Type == ui.KeyboardEvent {switch e.ID {case "q", "<C-c>":return}}}
}
(3)实时数据动态变化
package mainimport ("log""math/rand""time"ui "github.com/gizak/termui/v3""github.com/gizak/termui/v3/widgets"
)func main() {// 初始化 termuiif err := ui.Init(); err != nil {log.Fatalf("无法初始化 termui: %v", err)}defer ui.Close()// 创建标题title := widgets.NewParagraph()title.Text = "🎉 欢迎使用炫酷的 TermUI 应用 🎉"title.TextStyle = ui.NewStyle(ui.ColorYellow, ui.ColorClear, ui.ModifierBold)title.SetRect(0, 0, 50, 3)title.Border = false// 创建段落paragraph := widgets.NewParagraph()paragraph.Text = "这是一个使用 TermUI 构建的炫酷终端界面示例。按任意键退出。"paragraph.SetRect(0, 3, 50, 7)paragraph.TextStyle = ui.NewStyle(ui.ColorWhite)paragraph.Border = false// 创建条形图barchart := widgets.NewBarChart()barchart.Title = "实时数据"barchart.SetRect(0, 7, 50, 20)barchart.BarWidth = 6barchart.BarGap = 2barchart.BarColors = []ui.Color{ui.ColorGreen, ui.ColorYellow, ui.ColorRed}barchart.LabelStyles = []ui.Style{ui.NewStyle(ui.ColorBlack)}barchart.NumStyles = []ui.Style{ui.NewStyle(ui.ColorBlack)}barchart.BorderStyle = ui.NewStyle(ui.ColorCyan)// 创建列表list := widgets.NewList()list.Title = "功能列表"list.Rows = []string{"• 显示标题和段落","• 实时更新条形图","• 显示功能列表","• 支持键盘事件退出",}list.SetRect(50, 0, 80, 10)list.TextStyle = ui.NewStyle(ui.ColorWhite)list.BorderStyle = ui.NewStyle(ui.ColorMagenta)// 设置初始条形图数据barchart.Data = generateRandomData()// 渲染初始界面ui.Render(title, paragraph, barchart, list)// 启动一个定时器,每一秒更新一次条形图数据ticker := time.NewTicker(time.Second).Cgo func() {for {select {case <-ticker:barchart.Data = generateRandomData()ui.Render(barchart)}}}()// 监听键盘事件,按任意键退出for e := range ui.PollEvents() {if e.Type == ui.KeyboardEvent {break}}
}// 生成随机数据用于条形图
func generateRandomData() []float64 {rand.Seed(time.Now().UnixNano())data := make([]float64, 5)for i := range data {data[i] = rand.Float64() * 100}return data
}
(4)折线图、打印系统信息
package mainimport ("fmt""log""math/rand""runtime""time"ui "github.com/gizak/termui/v3""github.com/gizak/termui/v3/widgets"
)// padCenter 用于手动居中文本
func padCenter(text string, width int) string {if len(text) >= width {return text}padding := (width - len(text)) / 2return fmt.Sprintf("%*s%s%*s", padding, "", text, padding, "")
}func main() {// 初始化 termuiif err := ui.Init(); err != nil {log.Fatalf("无法初始化 termui: %v", err)}defer ui.Close()// 获取初始终端尺寸termWidth, termHeight := ui.TerminalDimensions()// 创建标题title := widgets.NewParagraph()title.Text = padCenter("🚀 炫酷的 TermUI 仪表盘示例 🚀", termWidth)title.TextStyle = ui.NewStyle(ui.ColorCyan, ui.ColorBlack, ui.ModifierBold)title.SetRect(0, 0, termWidth, 3)title.Border = false// 创建段落paragraph := widgets.NewParagraph()paragraph.Text = "欢迎使用 TermUI 构建的炫酷终端界面示例。按 'q' 键退出。"paragraph.SetRect(0, 3, termWidth, 6)paragraph.TextStyle = ui.NewStyle(ui.ColorWhite)paragraph.Border = false// 创建条形图barchart := widgets.NewBarChart()barchart.Title = "实时数据"barchart.SetRect(0, 6, termWidth/2, 18) // 调整高度barchart.BarWidth = 6barchart.BarGap = 2barchart.BarColors = []ui.Color{ui.ColorGreen, ui.ColorYellow, ui.ColorRed}barchart.LabelStyles = []ui.Style{ui.NewStyle(ui.ColorBlack)}barchart.NumStyles = []ui.Style{ui.NewStyle(ui.ColorBlack)}barchart.BorderStyle = ui.NewStyle(ui.ColorMagenta)barchart.Data = generateRandomData()// 创建折线图linechart := widgets.NewPlot()linechart.Title = "数据趋势"linechart.SetRect(termWidth/2, 6, termWidth, 18) // 调整高度linechart.AxesColor = ui.ColorWhitelinechart.LineColors[0] = ui.ColorYellowlinechart.Data = make([][]float64, 1)linechart.Data[0] = generateLineData()// 创建仪表盘gauge := widgets.NewGauge()gauge.Title = "CPU 使用率"gauge.SetRect(0, 18, termWidth/2, 21) // 调整高度gauge.BarColor = ui.ColorRedgauge.BorderStyle = ui.NewStyle(ui.ColorMagenta)gauge.LabelStyle = ui.NewStyle(ui.ColorWhite)gauge.Percent = 0// 创建列表list := widgets.NewList()list.Title = "功能列表"list.Rows = []string{"• 显示标题和段落","• 实时更新条形图","• 显示数据趋势折线图","• 显示 CPU 使用率仪表盘","• 显示功能列表和数据表","• 支持键盘事件退出",}list.SetRect(termWidth/2, 18, termWidth, 21) // 调整高度list.TextStyle = ui.NewStyle(ui.ColorWhite)list.BorderStyle = ui.NewStyle(ui.ColorGreen)// 创建表格table := widgets.NewTable()table.Title = "系统信息"table.Rows = [][]string{{"名称", "值"},{"操作系统", "Linux"},{"架构", "x86_64"},{"Go 版本", runtimeVersion()},{"TermUI 版本", termuiVersion()},}table.TextStyle = ui.NewStyle(ui.ColorWhite)table.RowSeparator = falsetable.FillRow = truetable.SetRect(0, 21, termWidth, termHeight-2) // 调整高度,避免最底部留白table.BorderStyle = ui.NewStyle(ui.ColorBlue)// 创建 Grid 布局grid := ui.NewGrid()grid.SetRect(0, 0, termWidth, termHeight)grid.Set(ui.NewRow(0.07,ui.NewCol(1.0, title),),ui.NewRow(0.07,ui.NewCol(1.0, paragraph),),ui.NewRow(0.45,ui.NewCol(0.5, barchart),ui.NewCol(0.5, linechart),),ui.NewRow(0.15,ui.NewCol(0.5, gauge),ui.NewCol(0.5, list),),ui.NewRow(0.16, // 减少表格占比ui.NewCol(1.0, table),),)// 渲染初始界面ui.Render(grid)// 初始化数据更新通道ticker := time.NewTicker(time.Second).C// 数据趋势折线图数据缓冲lineData := make([]float64, 50)for i := range lineData {lineData[i] = rand.Float64() * 100}// 启动一个 goroutine 进行数据更新go func() {for {select {case <-ticker:// 更新条形图数据barchart.Data = generateRandomData()// 更新折线图数据newValue := rand.Float64() * 100lineData = append(lineData[1:], newValue)linechart.Data[0] = lineData// 更新仪表盘数据gauge.Percent = int(newValue)// 重新渲染界面ui.Render(grid)}}}()// 监听键盘事件uiEvents := ui.PollEvents()for {e := <-uiEventsswitch e.ID {case "q", "<C-c>":returncase "<Resize>":// 获取新的终端尺寸termWidth, termHeight = ui.TerminalDimensions()// 更新标题文本居中title.Text = padCenter("🚀 炫酷的 TermUI 仪表盘示例 🚀", termWidth)// 更新所有小部件的 SetRect 参数title.SetRect(0, 0, termWidth, 3)paragraph.SetRect(0, 3, termWidth, 6)barchart.SetRect(0, 6, termWidth/2, 18)linechart.SetRect(termWidth/2, 6, termWidth, 18)gauge.SetRect(0, 18, termWidth/2, 21)list.SetRect(termWidth/2, 18, termWidth, 21)table.SetRect(0, 21, termWidth, termHeight-2) // 调整高度// 重新设置 Grid 布局比例grid.SetRect(0, 0, termWidth, termHeight)grid.Set(ui.NewRow(0.07,ui.NewCol(1.0, title),),ui.NewRow(0.07,ui.NewCol(1.0, paragraph),),ui.NewRow(0.45,ui.NewCol(0.5, barchart),ui.NewCol(0.5, linechart),),ui.NewRow(0.15,ui.NewCol(0.5, gauge),ui.NewCol(0.5, list),),ui.NewRow(0.16, // 减少表格占比ui.NewCol(1.0, table),),)// 重新渲染界面ui.Clear()ui.Render(grid)}}
}// generateRandomData 生成随机条形图数据
func generateRandomData() []float64 {data := make([]float64, 5)for i := range data {data[i] = rand.Float64() * 100}return data
}// generateLineData 生成初始折线图数据
func generateLineData() []float64 {data := make([]float64, 50)for i := range data {data[i] = rand.Float64() * 100}return data
}// runtimeVersion 获取 Go 版本
func runtimeVersion() string {return fmt.Sprintf("%s", runtime.Version())
}// termuiVersion 获取 termui 版本
func termuiVersion() string {return "v3.1.0" // 请根据实际使用的 termui 版本进行修改
}
相关文章:
Go语言入门
文章目录 零、Linux下Go的安装1.下载、解压2.添加环境变量3.验证安装4.初始化Go模块(1)cd到项目目录(2)初始化模块(3)获取依赖包(4)清理和验证依赖(5)检查 go.mod 文件(6)介绍 go.mod 和 go.sum 文件 5.项目目录结构 一、感性认识1.从 Hello world 开始2.加法函数 二、Go语法1.…...
VS Code中怎样查看某分支的提交历史记录
VsCode中无法直接查看某分支的提交记录,需借助插件才行,常见的插件如果git history只能查看某页面的改动记录,无法查看某分支的整体提交记录,我们可以安装GIT Graph插件来解决这个问题 1.在 VSCode的插件库中搜索 GIT Graph安装&a…...
【杂谈】-AI搜索引擎如何改变传统SEO及其在内容营销中的作用
AI搜索引擎如何改变传统SEO及其在内容营销中的作用 文章目录 AI搜索引擎如何改变传统SEO及其在内容营销中的作用1、什么是AI搜索引擎2、AI搜索引擎对SEO策略的影响3、AI搜索引擎在内容营销转型中的作用4、AI搜索引擎在营销领域的挑战、道德问题和未来5、总结 在当今的数字营销世…...
快速掌握Haproxy原理架构
文章目录 一、原理架构二、无负载均衡三、四层负载均衡的工作流程四、七层负载均衡工作流程五、基础属性mode 属性retries 属性maxconn 属性clitimeout 属性servtimeout 属性states uri 属性 一、原理架构 四层tcp代理:Haproxy仅在客户端和服务器之间双向转发流量&…...
Java中以某字符串开头且忽略大小写字母如何实现【正则表达式(Regex)】
第一种思路是先将它们都转换为小写或大写,再使用String类的startsWith()方法实现: 例如,如下的二个示例: "Session".toLowerCase().startsWith("sEsSi".toLowerCase()); //例子之一//例子之二String str "Hello Wo…...
如何提高Redis服务器的最大打开文件数限制
文章目录 如何提高Redis服务器的最大打开文件数限制问题诊断解决步骤1. 修改系统级别的限制2. 为Redis进程特别设置限制3. 修改Redis配置文件4. 修改systemd服务文件5. 重新加载systemd并重启Redis6. 验证更改 注意事项 如何提高Redis服务器的最大打开文件数限制 在运行高并发…...
React 组件通信完整指南 以及 自定义事件发布订阅系统
React 组件通信完整指南 1. 父子组件通信 1.1 父组件向子组件传递数据 // 父组件 function ParentComponent() {const [data, setData] useState(Hello from parent);return <ChildComponent message{data} />; }// 子组件 function ChildComponent({ message }) {re…...
代码随想录算法【Day5\Day6】
DAY5\Day6 1.熟悉哈希表的数据结构:数组、map和set,使用方法、使用场景 2.哈希表应用场景:解决给你一个元素,判断它在集合里是否出现过。 242.有效的字母异位词 本题用数组解决的。 class Solution { public:bool isAnagram(…...
Oracle 数据库执行计划的查看与分析技巧
目录 Oracle 数据库执行计划的查看与分析技巧一、什么是执行计划二、查看执行计划的方法(一)使用 EXPLAIN PLAN 命令(二)通过 SQL Developer 工具查看(三)启用 AUTOTRACE 功能 三、执行计划中的关键信息解读…...
VMD-SSA-BiLSTM、VMD-BiLSTM、BiLSTM时间序列预测对比
VMD-SSA-BiLSTM、VMD-BiLSTM、BiLSTM时间序列预测对比 目录 VMD-SSA-BiLSTM、VMD-BiLSTM、BiLSTM时间序列预测对比预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.MATLAB实现VMD-SSA-BiLSTM、VMD-BiLSTM、BiLSTM时间序列预测对比; 2.单变量时间序列预测 就是先vmd把变…...
QGIS二次开发(地图符号库操作)
实习三 地图符号库操作 3.1 任务要求 基于QGIS,实现地图符号的设计/存储与显示;基于QGIS实现一个点、线、面shp矢量图层文件的显示。通过设置引用的符号,改变矢量图层的显示效果;可编辑地图的符号库汇中的点符号、线符号、面符号…...
wordpress网站用token登入开发过程
生成跳转token 示例: function generate_login_token($user_id, $secret_key) {$payload [user_id > $user_id,timestamp > time(),];$payload_json json_encode($payload);$signature hash_hmac(sha256, $payload_json, $secret_key);return base64_en…...
Uniapp在浏览器拉起导航
Uniapp在浏览器拉起导航 最近涉及到要在浏览器中拉起导航,对目标点进行路线规划等功能,踩了一些坑,找到了使用方法。(浏览器拉起) 效果展示 可以拉起三大平台及苹果导航 点击选中某个导航,会携带经纬度跳转…...
在 CentOS 上安装 FFmpeg
在CentOS 上安装 FFmpeg 方法一:在线安装 添加 EPEL 和 RPM Fusion 源: sudo yum install epel-release sudo yum install https://download1.rpmfusion.org/free/el/rpmfusion-free-release-$(rpm -E %rhel).noarch.rpm安装 FFmpeg: sudo yu…...
影刀进阶指令 | liblib反推 (SD AI绘图反推)
文章目录 影刀进阶指令 | liblib反推 (SD AI绘图反推)一. 需求二. 流程三. 实现3.1 流程概览3.2 流程步骤讲解1\. 获取png地址2\. 打开页面3\. 上传png文件4\. 获取png的prompt信息 四. 运维 影刀进阶指令 | liblib反推 (SD AI绘图反推) 先看看我们要实现的功能,li…...
WebStorm 创建一个Vue项目
一、下载并安装WebStorm 步骤一 步骤二 选择激活方式 激活码: I2A0QUY8VU-eyJsaWNlbnNlSWQiOiJJMkEwUVVZOFZVIiwibGljZW5zZWVOYW1lIjoiVU5JVkVSU0lEQURFIEVTVEFEVUFMIERFIENBTVBJTkFTIiwiYXNzaWduZWVOYW1lIjoiVGFvYmFv77yaSkVU5YWo5a625qG25rAIOa0uW3peS9nOWupC…...
回归预测 | MATLAB实现CNN-LSTM卷积长短期记忆神经网络多输入单输出回归预测
回归预测 | MATLAB实现CNN-LSTM卷积长短期记忆神经网络多输入单输出回归预测 目录 回归预测 | MATLAB实现CNN-LSTM卷积长短期记忆神经网络多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 MATLAB实现CNN-LSTM卷积长短期记忆神经网络多输入单输出回归…...
rust windwos 两个edit框
use winapi::shared::minwindef::LOWORD; use windows::{core::*,Win32::{Foundation::*,Graphics::Gdi::{BeginPaint, EndPaint, PAINTSTRUCT},System::LibraryLoader::GetModuleHandleA,UI::WindowsAndMessaging::*,}, };// 两个全局静态变量,用于保存 Edit 控件的…...
ArcGIS计算矢量要素集中每一个面的遥感影像平均值、最大值等统计指标
本文介绍在ArcMap软件中,基于矢量面要素集,计算在其中每一个面区域内,遥感影像的像元个数、平均值、总和等统计值,并将统计信息附加到矢量图层的属性表中的方法。 首先,明确一下本文的需求。现在有一个矢量面要素集&am…...
JavaScript高级程序设计基础(十一)
上接语言基础:JavaScript高级程序设计基础(十) 五、集合引用类型 5.1 object 此处简单介绍object,object由两种方式可以创造:由构造函数new Object(),或者对象字面量。如果想要修改对象的值可以用点语法,如object.na…...
【服务器学习专栏 1.2 -- 带外管理】
请阅读 嵌入式学习必备专栏 文章目录 Overview服务器带外管理BMC 介绍BMC 特点BMC 工作原理 Overview 从技术的角度,网络管理可分为带外管理(out-of-band)和带内管理(in-band)两种管理模式。 带内管理,是指…...
《Vue3 二》Vue 的模板语法
在 React 中,想要编写 HTML,是使用 JSX,之后通过 Babel 将 JSX 编译成 React.createElement 函数调用;在 Vue 中,也支持 JSX 的开发模式,但大多数情况下都是使用基于 HTML 的模板语法,在模板中允…...
手机租赁平台开发全攻略打造高效便捷的租赁服务系统
内容概要 手机租赁平台开发,简单说就是让用户能轻松租赁各类手机的高效系统。这一平台不仅帮助那些想要临时使用高端手机的人们节省了不少资金,还为商家开辟了新的收入渠道。随着智能手机的普及,很多人并不需要长期拥有一部手机,…...
【Ext.js 初步入门】Ext.js 作用以及用法 概述
一、Ext.js的作用 首先我们需要了解类似Ext.js以及easyui类似产品的作用是什么。 我的理解是就是相当于一个组件库,它与bootstrap类似产品的区别在于,bootstrap与ext.js和easyui面向的问题不同,bootstrap面向的问题样式,ext.js和…...
基于源码剖析:深度解读JVM底层运行机制
每日禅语 佛说,给你修路的,是你自己;埋葬你的,也是你自己;帮助你的,是你自己;毁灭你的,也是你自己;成就你的,自然还是你自己。所以佛说:自作自受&…...
redis延迟队列
Redis延迟队列 Redis延迟队列是基于Redis构建的消息队列,用来处理需延迟执行的任务。 基本原理 它借助Redis的有序集合(Sorted Set)数据结构达成目的。会把任务及其执行时间分别当成成员与分值存进有序集合,由于执行时间作为分值&…...
GDPU Vue前端框架开发 期末赛道出勇士篇(更新ing)
记住,年底陪你跨年的不会仅是方便面跟你的闺蜜,还有孑的笔记。 选择题 1.下列选项用于设置Vue.js页面视图的元素是()。 A. Template B. script C. style D. title 2.下列选项中能够定义Vuejs根实例对象的元素是(&…...
WordPress TutorLMS插件 SQL注入漏洞复现(CVE-2024-10400)(附脚本)
0x01 产品描述: Tutor LMS是一个功能强大的...
小程序配置文件 —— 14 全局配置 - tabbar配置
全局配置 - tabBar配置 tabBar 字段:定义小程序顶部、底部 tab 栏,用以实现页面之间的快速切换;可以通过 tabBar 配置项指定 tab 栏的表现,以及 tab 切换时显示的对应页面; 在上面图中,标注了一些 tabBar …...
基于python+Django+mysql文档格式转换工具系统设计与实现
博主介绍:黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育、辅导。 所有项目都配有从入门到精通的基础知识视频课程ÿ…...
异步线程池中,ThreadPoolTaskExecutor和ThreadPoolExecutor有什么区别?
异步线程池中,org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor和java.util.concurrent.ThreadPoolExecutor有什么区别? org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor 和 java.util.concurrent.ThreadPoolExec…...
【机器学习】SVM支持向量机(二)
介绍 支持向量机(Support Vector Machine, SVM)是一种监督学习模型,广泛应用于分类和回归分析。SVM 的核心思想是通过找到一个最优的超平面来划分不同类别的数据点,并且尽可能地最大化离该超平面最近的数据点(支持向量…...
基于NodeMCU的物联网电灯控制系统设计
最终效果 基于NodeMCU的物联网电灯控制系统设计 小程序关灯 上图展现了小程序关灯过程的数据传输过程:用户下达关灯指令→小程序下发关灯指令→MQTT服务器接收关灯指令→下位机接收与处理关灯指令。 项目介绍 该项目是“物联网实验室监测控制系统设计(…...
源码安装redis后配置redis开机自启动
initd风格 #!/bin/sh ### BEGIN INIT INFO # Provides: redis # Required-Start: $remote_fs $syslog # Required-Stop: $remote_fs $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start/stop Redis server ### END…...
WebRTC服务质量(11)- Pacer机制(03) IntervalBudget
WebRTC服务质量(01)- Qos概述 WebRTC服务质量(02)- RTP协议 WebRTC服务质量(03)- RTCP协议 WebRTC服务质量(04)- 重传机制(01) RTX NACK概述 WebRTC服务质量(…...
22.跳过报错(最简) C#例子
这是一个跳过报错的例子,如果代码出错了会自动跳过,代码正确了就正常执行。 然而这不是一种推荐的做法,正确的做法应该是使用bool类型的值去检测代码运行结果,然后分支判断,在代码内部解决错误。 这只是一种好玩的做…...
windows 本地node版本快速升级
文章目录 前言一、前置条件二、使用步骤1.查看node 安装位置2.下载指定的node 版本3.下载后进行解压缩4. 删除覆盖原来的node文件夹内容5. 验证 总结 前言 Node.js 是一个开源、跨平台的JavaScript运行时环境,它允许开发者在服务器端运行JavaScript代码。Node.js 基…...
windows安装mongodb
一.安装包准备 1.服务端下载 https://www.mongodb.com/try/download/communitya 按需选择,我们这里选择社区版 直接点download浏览器下载可能比较慢,可以尝试copy link后用三方下载软件,会快很多。 2.命令行客户端下载 https://www.mong…...
一文读懂混合专家模型(MoE)
一文读懂混合专家模型(MoE) 概述 混合专家模型(Mixture of Experts,MoE)是一种机器学习和深度学习中的模型架构,它通过多个“专家”子模型来处理不同类型的输入数据或任务。在MoE模型中,输入数…...
自然语言处理(NLP)中的事件检测和事件抽取
事件检测和事件抽取是自然语言处理(NLP)中的两个重要任务,主要用于从文本中识别和提取事件及其相关信息。这两个任务在信息检索、情报分析、新闻摘要等应用中具有重要意义。 事件检测(Event Detection) 事件检测的目…...
深度学习:基于MindSpore NLP的数据并行训练
什么是数据并行? 数据并行(Data Parallelism, DP)的核心思想是将大规模的数据集分割成若干个较小的数据子集,并将这些子集分配到不同的 NPU 计算节点上,每个节点运行相同的模型副本,但处理不同的数据子集。…...
unity NAudio 获取电脑是否静音
测试,这两个办法都可以 打包出来也可以hu 想获取电脑是否静音出现编辑器模式下正常 打包出来失败 需要把 Api Compatibility Level改成.NET 4.x...
SemiDrive E3 MCAL 开发系列(6)– Icu 模块的使用
一、 概述 本文将会介绍 SemiDrive E3 MCAL Icu 模块的简介以及基本配置,其中还会涉及到 Xtrg 模块的配置。此外会结合实际操作的介绍,帮助新手快速了解并掌握这个模块的使用,文中的 MCAL 是基于 PTG3.0 的版本,开发板是官方的 …...
leetCode322.零钱兑换
题目: 给你一个整数数组coins,表示不同面额的硬币;以及一个整数amount,表示总金额。 计算并返回可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回-1。 你可以认为每种硬币的数量是无限的。 示例1࿱…...
【Python】什么是元组(Tuple)?
什么是元组(Tuple)? 元组(Tuple)是 Python 中的一种 不可变 的数据结构,用于存储多个元素。它类似于列表(List),但与列表不同的是,元组一旦创建,…...
zentao ubuntu上安装
#下载ZenTaoPMS-21.2-zbox_amd64.tar.gz(https://www.zentao.net/downloads.html) https://dl.zentao.net/zentao/21.2/ZenTaoPMS-21.2-zbox_amd64.tar.gzcd /opt tar -zxvf ZenTaoPMS-21.2-zbox_amd64.tar.gz#启动 /opt/zbox/zbox start /opt/zbox/zbox…...
文档解析丨高效准确的PDF解析工具,赋能企业非结构化数据治理
在数据为王的时代浪潮中,企业数据治理已成为组织优化运营、提高竞争力的关键。随着数字化进程的加速,企业所积累的数据量呈爆炸式增长,数据类型也愈发多样化,这些数据构成了现代企业数据资产的重要组成部分。 然而,传…...
Unity 实现Canvas显示3D物体
新建一个UI相机,选择渲染层为UI 将主相机的渲染层去掉UI层 、 将Canvas的RenderMode设置为Screen Space - Camera,将RenderCamera设置为UI相机 新建3D物体的UI父物体,并将3D物体的层级设置为UI层 适当的放缩3DObjParent,让3D物体能显示出来…...
OpenAI 12天发布会:AI革命的里程碑@附35页PDF文件下载
在人工智能的浪潮中,OpenAI的12天发布会无疑是2024年科技界的一场盛宴。从12月5日开始,OpenAI连续12天每天发布一个新应用或功能,标志着AI技术的又一次飞跃。本文将梳理这些激动人心的发布,带你一探究竟。 OpenAI发布会概览 Ope…...
cellphoneDB进行CCI以及可视化
除了cellchat,在单细胞转录组或者空间组的分析中,cellphoneDB也是一个常用的细胞通讯软件,这个数据库更注重配受体关系,对于有明确先验知识的配受体研究比较友好。 但值得注意的是,它的数据库只包括人的基因名称信息&…...