用Go+Vue编写自己的轻量工具软件(服务端监控和reids客户端)

前言

有需要编写前后端配合的软件,轻量且跨平台,快速就能开发一个属于自己的小工具。

思路

  • Go语言负责后端,获取磁盘信息,连接数据库等前端无法胜任的活路
  • Vue负责页面编写,调用后端接口,vue3一键生成开发模版,即刻上手,使用ElementPlus,美滋滋
  • 使用Go内置技术,将前端dist包内嵌入程序中,单文件exe运行够清爽
  • 每个客户端独立保存配置,可以用前端浏览器缓存,也可以后端用sqlite,都是轻量级

使用技术

  • 前端:Vue3、Vite、ElementPlus、axios
  • 后端:go1.20、systray、go-redis

开始操作

前端

封装axios请求后端api

js 复制代码
import axios from 'axios'
import { ElNotification , ElMessageBox, ElMessage, ElLoading } from 'element-plus'

axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const service = axios.create({
  // axios中请求配置有baseURL选项,表示请求URL公共部分
  baseURL: '/monitor-api',
  // 超时
  timeout: 40000
})

service.interceptors.response.use(res => {
  // 拦截器
})

export default service

路由添加

js 复制代码
const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    {
      path: '/',
      name: 'home',
      component: () => import('@/views/monitor/index.vue')
    },
    {
      path: '/redis',
      name: 'redis',
      component: () => import('@/views/redis/index.vue')
    },
  ]
})

export default router

页面编写, 根据业务自己写, 打包应用yarn build

后端

初始化项目

shell 复制代码
go mod init dmonitor

下载依赖

shell 复制代码
go get -u github.com/redis/go-redis/v9
...

编写代码

  1. 主函数
  • 通过go:embed 指定静态资源目录, 可以直接将前端打包的资源封装入exe中
  • http.HandleFunc 将api前缀交给函数处理, 在函数里面具体处理子路由
  • 匿名函数go func() {}(), 不会阻塞主进程
go 复制代码
//go:embed webapp
var f embed.FS

func main() {
  // 端口配置可以通过运行参数指定
	port := flag.Int("p", 40001, "server port")
	base.RunPort = *port
	flag.Parse()
	addr := fmt.Sprintf(":%d", *port)

	http.HandleFunc("/monitor-api/info", getInfoHandler)
	http.HandleFunc("/monitor-api/redis/", redis.HandleApi)

	st, _ := fs.Sub(f, "webapp")
	// 将文件服务器注册到指定路径
	http.Handle("/", http.StripPrefix("/", http.FileServer(http.FS(st))))

	fmt.Printf("***********************app run on http://localhost:%d/ *******************", *port)
	fmt.Println("")

	utils.OpenBrowser(fmt.Sprintf("http://localhost:%d/", *port))
	go func() {
		utils.GenTaskBarIcon()
	}()

	fmt.Println("start http.... ", *port)
	err := http.ListenAndServe(addr, nil)
	if err != nil {
		fmt.Println("start http error: ", err)
	}
	fmt.Println("start http success ", *port)
}
  1. HandleApi 处理子路由
go 复制代码
func HandleApi(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Access-Control-Allow-Origin", "*")             //允许访问所有域
	w.Header().Add("Access-Control-Allow-Headers", "Content-Type") //header的类型
	w.Header().Set("Content-Type", "application/json")

	path := r.URL.Path
	fmt.Println("redis HandleApi path:", path)

	switch {
	case strings.Contains(path, "/getRedisDbInfo"):
		getRedisDbInfo(w, r)
	case strings.Contains(path, "/changeRedisDb"):
		changeRedisDb(w, r)
	case strings.Contains(path, "/pingRedis"):
		pingRedis(w, r)
	case strings.Contains(path, "/initRedis"):
		initRedis(w, r)
	case strings.Contains(path, "/listKey"):
		listKey(w, r)
	case strings.Contains(path, "/getByKey"):
		getByKey(w, r)
	default:
		http.NotFound(w, r)
	}
}
  1. windows任务栏添加应用小图标和菜单
go 复制代码
func GenTaskBarIcon() {
	if runtime.GOOS == "windows" {
		systray.Run(onReady, onExit)
	}
}

func onReady() {
	systray.SetIcon(iconData)
	systray.SetTitle("D-Monitor")
	systray.SetTooltip("D-Monitor 右键点击打开菜单!")
	menuOpen := systray.AddMenuItem("打开网页", "打开系统网页")
	systray.AddSeparator()
	menuQuit := systray.AddMenuItem("退出", "退出程序")

	go func() {
		for {
			select {
			case <-menuOpen.ClickedCh:
				OpenBrowser(fmt.Sprintf("http://localhost:%d/", base.RunPort))
			case <-menuQuit.ClickedCh:
				systray.Quit()
				os.Exit(0)
			}
		}
	}()

}

func onExit() {}
  1. 针对linux和windows写不同的工具函数, 因为不同平台用的函数可能不一样, 会造成编译失败, go只能针对文件级别来区别平台编译, 所以在文件开头加入注释//go:build [platform]
go 复制代码
// utils/linux.go

//go:build linux
package utils

func OpenBrowser(url string) error {
	return nil
}
go 复制代码
// utils/windows.go

//go:build windows
package utils

func OpenBrowser(url string) error {
	var cmd string
	var args []string

	switch runtime.GOOS {
	case "windows":
		cmd = "cmd"
		args = []string{"/c", "start"}
	default: // Linux 等其他 Unix-like 系统
		cmd = ""
	}
	if cmd == "" {
		return nil
	}

	args = append(args, url)
	ec := exec.Command(cmd, args...)
	if runtime.GOOS == "windows" {
		ec.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
	}
	return ec.Start()
}
  1. 打包脚本 build.sh
shell 复制代码
#!/bin/bash

set -eu

VERSION=$(git describe --abbrev=0 --tags)
REVCNT=$(git rev-list --count HEAD)
DEVCNT=$(git rev-list --count $VERSION)
if test $REVCNT != $DEVCNT
then
	VERSION="$VERSION.dev$(expr $REVCNT - $DEVCNT)"
fi
echo "VER: $VERSION"

GITCOMMIT=$(git rev-parse HEAD)
BUILDTIME=$(date -u +%Y/%m/%d-%H:%M:%S)

LDFLAGS="-X main.VERSION=$VERSION -X main.BUILDTIME=$BUILDTIME -X main.GITCOMMIT=$GITCOMMIT"
if [[ -n "${EX_LDFLAGS:-""}" ]]
then
	LDFLAGS="$LDFLAGS $EX_LDFLAGS"
fi

build() {
	echo "$1 $2  $3... $LDFLAGS"
  LDFLAGS1="$LDFLAGS"
  if [ "$1" = "windows" ]; then
    LDFLAGS1="$LDFLAGS -H=windowsgui"
  fi
  echo "LDFLAGS1... $LDFLAGS1"
	GOOS=$1 GOARCH=$2 go build \
		-ldflags "-s -w $LDFLAGS1" \
		-o dist/dmonitor-${3:-""}
}

build linux arm linux-arm
# build darwin amd64 mac-amd64
build linux amd64 linux-amd64
build linux 386 linux-386
build windows arm64 win-arm64.exe
build windows amd64 win-amd64.exe

后言

至此就能开发一个自己的轻量小工具,目前通过go+vue开发了一个服务端监控软件, 可以实时监控服务器的CPU、内存、磁盘、进程等使用情况,也集成了简易的redis客户端,可以连接到redis并查看键值, upx压缩后也就2M左右,够轻便了

源码地址

相关推荐
研究司马懿11 小时前
【云原生】Gateway API高级功能
云原生·go·gateway·k8s·gateway api
梦想很大很大1 天前
使用 Go + Gin + Fx 构建工程化后端服务模板(gin-app 实践)
前端·后端·go
lekami_兰1 天前
MySQL 长事务:藏在业务里的性能 “隐形杀手”
数据库·mysql·go·长事务
却尘1 天前
一篇小白也能看懂的 Go 字符串拼接 & Builder & cap 全家桶
后端·go
ん贤1 天前
一次批量删除引发的死锁,最终我选择不加锁
数据库·安全·go·死锁
mtngt112 天前
AI DDD重构实践
go
Grassto3 天前
12 go.sum 是如何保证依赖安全的?校验机制源码解析
安全·golang·go·哈希算法·go module
Grassto5 天前
11 Go Module 缓存机制详解
开发语言·缓存·golang·go·go module
程序设计实验室6 天前
2025年的最后一天,分享我使用go语言开发的电子书转换工具网站
go
我的golang之路果然有问题6 天前
使用 Hugo + GitHub Pages + PaperMod 主题 + Obsidian 搭建开发博客
golang·go·github·博客·个人开发·个人博客·hugo