用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左右,够轻便了

源码地址

相关推荐
27669582921 天前
阿里1688 阿里滑块 231滑块 x5sec分析
java·python·go·验证码·1688·阿里滑块·231滑块
Moment2 天前
在 NodeJs 中如何通过子进程与 Golang 进行 IPC 通信 🙄🙄🙄
前端·后端·go
唐僧洗头爱飘柔95273 天前
(Go基础)变量与常量?字面量与变量的较量!
开发语言·后端·golang·go·go语言初上手
黑心萝卜三条杠3 天前
【Go语言】深入理解Go语言:并发、内存管理和垃圾回收
google·程序员·go
不喝水的鱼儿3 天前
【LuatOS】基于WebSocket的同步请求框架
网络·websocket·网络协议·go·luatos·lua5.4
微刻时光3 天前
程序员开发速查表
java·开发语言·python·docker·go·php·编程语言
lidenger4 天前
服务认证-来者何人
后端·go
幼儿园老大*4 天前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
童先生4 天前
Go 项目中实现类似 Java Shiro 的权限控制中间件?
开发语言·go
幼儿园老大*4 天前
走进 Go 语言基础语法
开发语言·后端·学习·golang·go