ساخت اپلیکیشن دسکتاپ تحت Go با Wails – از صفر تا صد
چنانکه میدانیم Go به طور عمده برای ساoت API-ها، بکاند وب و ابزارهای CLI استفاده میشود. اما نکته جالب این جا است که میتوان از Go در جاهایی که هیچ انتظار نمیرود نیز استفاده کرد. برای نمونه میتوانیم با بهرهگیری از فریمورک Wails (+) یک اپلیکیشن دسکتاپ با Go و Vue.js بسازیم.
این فریمورک جدید است و همچنان در مرحله بتا قرار دارد، اما شیوه کار کردن با آن و ساخت و پکیج کردن اپلیکیشن در آن به طرز شگفت انگیزی آسان است. Wails امکان قرار دادن کد Go و یک فرانت وب را در یک فایل باینری منفرد فراهم ساخته است. CLI این فریمورک این کار را به آسانی ممکن ساخته است و فرایند ایجاد، کامپایل و ساخت پروژه را به سهولت انجام میدهد.
اپلیکیشن دسکتاپ تحت Go
ما قصد داریم که اپلیکیشن سادهای برای نمایش میزان مصرف CPU رایانه به صورت آنی بسازیم. اگر شما زمان کافی دارید و به Wails نیز علاقهمند هستید، میتوانید اپلیکیشن خلاقانهتر و پیچیدهتری نیز بسازید.
نصب
Wails CLI را میتوانید با اجرای دستور go get نصب کنید. پس از نصب کردن باید آن را با استفاده از دستور wails setup راهاندازی کنید.
go get github.com/wailsapp/wails/cmd/wails wails setup
بدین ترتیب پروژه ما با نام cpustats بوتاسترپ میشود:
wails init cd cpustats
پروژه ما شامل بکاند Go و فرانتاند Vue.js است. main.go نقطه ورود اپلیکیشن است که در آن میتوانیم وابستگیهای دیگر را قرار دهیم و یک فایل به نام go.mod نیز وجود دارد که آنها را مدیریت میکند. پوشه frontend شامل کامپوننتهای Vue.js وب پک و CSS است.
مفاهیم
2 کامپوننت اصلی به نامهای Binding and Events در اپلیکیشن وجود دارد که دادهها را بین بکاند و فرانتاند به اشتراک میگذارند. Binding یک متد منفرد است که امکان افشای (اتصال) کد Go به فرانتاند را فراهم میسازد.
ضمناً Wails یک سیستم متحد رویداد (Events) مشابه سیستم رویداد نیتیو جاوا اسکریپت عرضه میکند. این بدان معنی است که هر رویدادی که از Go یا جاوا اسکریپت ارسال شود، میتواند از هر دو سمت دریافت شود. دادهها را میتوان به همراه هر رویدادی ارسال کرد. بدین ترتیب میتوانیم کارهای جالبی مانند اجرای پردازشهای پسزمینه در Go داشته باشیم و هر گونه بهروزرسانی را به فرانتاند اطلاع دهیم.
بکاند
ابتدا سمت بکاند را توسعه میدهیم. برای دریافت میزان مصرف CPU و ارسال آن به فرانتاند از متد bind استفاده میکنیم.
ما یک پکیج جدید ایجاد کرده و یک نوع تعریف میکنیم که به فرانتاند وصل میشود.
فایل pkg/sys/sys.go:
1package sys
2import (
3 "math"
4 "time"
5 "github.com/shirou/gopsutil/cpu"
6 "github.com/wailsapp/wails"
7)
8// Stats .
9type Stats struct {
10 log *wails.CustomLogger
11}
12// CPUUsage .
13type CPUUsage struct {
14 Average int `json:"avg"`
15}
16// WailsInit .
17func (s *Stats) WailsInit(runtime *wails.Runtime) error {
18 s.log = runtime.Log.New("Stats")
19 return nil
20}
21// GetCPUUsage .
22func (s *Stats) GetCPUUsage() *CPUUsage {
23 percent, err := cpu.Percent(1*time.Second, false)
24 if err != nil {
25 s.log.Errorf("unable to get cpu stats: %s", err.Error())
26 return nil
27 }
28 return &CPUUsage{
29 Average: int(math.Round(percent[0])),
30 }
31}
اگر struct شما دارای یک متد WailsInit باشد، Wails آن را در ابتدای راهاندازی فرا میخواند. به این ترتیب میتوانید نوعی مقداردهی اولیه پیش از اجرای اپلیکیشن اصلی داشته باشید. پکیج sys را در main.go ایمپورت کنید و وهله Stats را به فرانتاند اتصال دهید:
1package main
2import (
3 "github.com/leaanthony/mewn"
4 "github.com/plutov/packagemain/cpustats/pkg/sys"
5 "github.com/wailsapp/wails"
6)
7func main() {
8 js := mewn.String("./frontend/dist/app.js")
9 css := mewn.String("./frontend/dist/app.css")
10 stats := &sys.Stats{}
11 app := wails.CreateApp(&wails.AppConfig{
12 Width: 512,
13 Height: 512,
14 Title: "CPU Usage",
15 JS: js,
16 CSS: css,
17 Colour: "#131313",
18 })
19 app.Bind(stats)
20 app.Run()
21}
فرانتاند
وهله stats را از Go اتصال میدهیم که میتواند با فراخوانی window.backend.Stats در فرانتاند استفاده شود. اگر بخواهیم تابعی به نام ()GetCPUUsage را فراخوانی کنیم، یک Promise به ما بازگشت میدهد:
1window.backend.Stats.GetCPUUsage().then(cpu_usage => {
2 console.log(cpu_usage);
3})
برای ساخت کل پروژه در یک کتابخانه منفرد، باید دستور wails build را اجرا کنیم، فلگ d- را میتوان برای ساخت نسخه قابل دیباگ استفاده کرد. این فلگ یک فایل باینری ایجاد میکند که نام آن با نام پروژه منطبق است. اینک آن را تست میکنیم که با نمایش ساده مصرف CPU روی صفحه کار میکند:
wails build -d ./cpustats
رویدادها
ما مقدار مصرف CPU را با استفاده از Binding به فرانتاند ارسال میکنیم. سپس تلاش میکنیم رویکرد متفاوتی را امتحان کنیم. در ادامه یک تایمر روی بکاند ایجاد میکنیم که مقادیر مصرف CPU را با استفاده از رویکرد Events به پسزمینه ارسال میکند. سپس میتوانیم در آن رویداد در جاوا اسکریپت ثبتنام کنیم. در Go این کار با تابع WailsInit انجام مییابد:
1func (s *Stats) WailsInit(runtime *wails.Runtime) error {
2 s.log = runtime.Log.New("Stats")
3 go func() {
4 for {
5 runtime.Events.Emit("cpu_usage", s.GetCPUUsage())
6 time.Sleep(1 * time.Second)
7 }
8 }()
9 return nil
10}
در Vue.js میتوانیم هنگامی که کامپوننت نصب میشود یا در هر مکان دیگری، در این رویداد ثبتنام کنیم:
1mounted: function() {
2 wails.events.on("cpu_usage", cpu_usage => {
3 if (cpu_usage) {
4 console.log(cpu_usage.avg);
5 }
6 });
7}
نوار Gauge
نمایش مصرف CPU با نوار Gauge میتواند مناسب باشد، بنابراین یک وابستگی شخص ثالث برای آن بگنجانیم و به این منظور میتوانیم از npm استفاده کنیم:
npm install --save apxcharts npm install --save vue-apexcharts
سپس آن را در فایل main.js ایمپورت میکنیم:
import VueApexCharts from 'vue-apexcharts' Vue.use(VueApexCharts) Vue.component('apexchart', VueApexCharts)
اکنون میتوانیم مصرف CPU را با استفاده از apexcharts نمایش دهیم و مقادیر کامپوننت را با دریافت یک رویداد از بکاند بهروزرسانی کنیم:
1<template>
2 <apexchart type="radialBar" :options="options" :series="series"></apexchart>
3</template>
4<script>
5export default {
6 data() {
7 return {
8 series: [0],
9 options: {
10 labels: ['CPU Usage']
11 }
12 };
13 },
14 mounted: function() {
15 wails.events.on("cpu_usage", cpu_usage => {
16 if (cpu_usage) {
17 this.series = [ cpu_usage.avg ];
18 }
19 });
20 }
21};
22</script>
برای تغییر دادن استایل میتوانیم مستقیماً فایل src/assets/css/main.css را اصلاح کنیم و یا آنها را در کامپوننتها تعریف کنیم.
بیلد و اجرای نهایی
wails build -d ./cpustats
سخن پایانی
کار با Wails کاملاً لذتبخش است و مفهوم رویدادها موجب شده که کنترل حالت اپلیکیشن واقعاً آسان شود. کد کامل پروژه معرفی شده در این مقاله را میتوانید در این ریپوی گیتهاب (+) ملاحظه کنید.
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای برنامهنویسی
- مجموعه آموزشهای دروس علوم و مهندسی کامپیوتر
- ۱۰ اشتباه رایج در پروژه های Go — راهنمای کاربردی
- پکیجهای زبان برنامهنویسی Go — از صفر تا صد
- چرا باید زبان برنامهنویسی Go را بیاموزیم؟ — راهنمای جامع
==