重写POS系统的技术栈选择建议(Golang版)

重写POS系统的技术栈选择建议(Golang版) 大家好,

我们公司有一个名为 POS(销售点)的应用程序,负责处理客户交易。为了便于理解,可以想象一下超市或便利店的收银系统,在那里扫描商品、应用折扣并处理付款。我们当前的 POS 系统是使用一种遗留编程语言构建的,管理层现在希望使用现代技术对其进行重写。

作为这项计划的一部分,我们正在评估各种编程语言,而 Go (Golang) 是正在考虑的选项之一。

现有的 POS 是一个 基于 Windows 的单体应用程序,我们的目标是 将其模块化为独立的服务,可能会遵循微服务架构。根据我的研究,Go 似乎非常适合:

  • 后端开发
  • 构建微服务
  • 编写设备驱动程序和进行硬件集成

然而,Go 并不被广泛推荐用于 UI 开发,这主要是因为在创建丰富的桌面界面方面,成熟的库和生态系统支持有限。

我想就以下几点收集大家的意见:

  1. 对于构建一个 端到端(包括 UI)的 POS 应用程序,Go 是一个可行的选择吗
  2. 如果不是,对于开发一个现代、可维护的 POS 系统,您会推荐什么 语言或技术栈

由于我们是从头开始,也欢迎提出 跨平台或基于 Web 的解决方案,而不仅仅是基于 Windows 的开发。

期待您的想法和建议。


更多关于重写POS系统的技术栈选择建议(Golang版)的实战教程也可以访问 https://www.itying.com/category-94-b0.html

7 回复

你好,

你可以使用 Pascal、C# 来开发前端。

这将帮助你快速进行数据录入和外部硬件集成。

使用 Go 语言开发 API。

你可以在其中使用 Redis 进行缓存,从而使你的应用程序运行得更快。

更多关于重写POS系统的技术栈选择建议(Golang版)的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你好,我有一款旧的.NET应用,它被安装为信息亭应用。因此,我正在考虑将它们迁移到Go,并且现在遇到了和你一样的问题。我搜索了一下,发现有很多UI库可以与Go一起使用。最常用的是Fyne、Wails和Gio,还有其他一些(只需搜索“UI golang libraries”即可)。我认为你需要评估它们,以选择最适合你的那个。

你好,

关于UI的选择,这很大程度上取决于你的具体需求和限制条件。 如果你需要一个独立的应用程序(一个同时包含后端功能的UI应用),我可以推荐:

对于客户端/服务器架构的应用程序,我建议使用Go语言开发后端,并使用Web应用(如Angular、React、Vue等)来构建UI。 为了使部署更简单,你也可以将UI应用嵌入到后端可执行文件中。

有趣且不错,因为有很多可用的选项。我认为构建Web UI可能会更容易,因为有很多工具和框架,并且可以在信息亭设备之外进行测试。在这种情况下,Wails最适合使用Go来开发你的UI。

话虽如此,似乎使用例如Electron,JavaScript也能胜任。如果你是.NET方向的开发者,C#也提供了一个很好的选择。

就我而言,应用程序是用.NET和C#编写的,并与Web API连接。我的问题是需要安装.NET运行时,而且信息亭提供的硬件有限,但到目前为止运行良好。

所以,如果你想使用Go作为基础工具,有很多UI库,包括基于Web的和原生组件(例如QT)。Go是开发后端代码的绝佳选择。

Yamil_Bracho:

最常用的是 Fyne、Wails 和 Gio 等(只需谷歌搜索“UI golang libraries”)。我认为你需要评估它们以选择最合适的。

根据我目前所做的研究,通常不建议将 Go 用于 UI 开发。Go 的 UI 生态系统仍不成熟,缺乏构建生产级界面通常所需的社区支持和工具水平。

考虑到这不是传统的客户端-服务器架构,并且我们的目的是在同一台机器上运行 UI 和后端,你仍然会推荐使用像 Angular 或 React 这样的前端框架吗?

此外,也有人建议使用 C# 而不是 Go 来开发这个 POS 应用程序。我也想听听你对此的看法——尤其是在构建功能齐全的 POS 系统的背景下。

谢谢。

这是一个让贵公司为技术栈的各个部分选择合适技术的绝佳机会。审视Go语言的一种方式是回顾其设计者旨在解决的问题。

  1. 简单、高度可读的语法(仅25个关键字,静态极简类型模型等)
  2. 通过运行时实现的高规模、高效率。开发者可以利用并发和并行,而无需微观管理其实现。
  3. 跨平台且真正高效——跨平台编译开箱即用,在POS基础架构正在并将持续变化的领域,从Intel迁移到ARM再到未来的平台,是开发者无需担心的又一个难题。此外,并发、映射类型和其他高级概念确实使用了极低的内存。

POS是B2C业务,这意味着面向客户的用例和灵活性至关重要。使用Go,你可以编写后端,完全启用API,并实现极快的数据处理。你可以在多个平台上做到这一点。在那里划定界限,然后使用React或你选择的UI工具和框架在其之上构建。

我用Go和React构建了这个服务/网站。它已在互联网上运行,并受到我运行的多个网站和蜜罐的猛烈冲击。总内存消耗?20MB。是的,20MB。现在,Go的运行时设置了大约1.5GB的限制,但这个服务持续承受API请求,拥有一个嵌入式NoSQL类型存储,并且不断更新。前面没有Nginx……它本身也是一个Web服务器。我已经一年多没有重启它了。

https://bruteforce.live

UI好吗?不,我是一个后端、服务器端和CLI开发者,但React前端有一个地图,看板上的更新会跃然空中,实时攻击会闪烁显示。

利用Go的效率,真正重新构想你的架构,将其分解为适当的服务,并使用最佳技术来完成每一层的设计目标。

对于重写POS系统,Go语言在核心后端和微服务方面是优秀选择,但在UI层需要结合其他技术。以下是具体分析:

1. Go在POS系统中的适用性

后端/微服务层(推荐使用Go):

// 商品服务示例
package main

import (
    "encoding/json"
    "net/http"
)

type Product struct {
    ID       string  `json:"id"`
    Name     string  `json:"name"`
    Price    float64 `json:"price"`
    Barcode  string  `json:"barcode"`
}

func productHandler(w http.ResponseWriter, r *http.Request) {
    product := Product{
        ID:      "P001",
        Name:    "矿泉水",
        Price:   2.50,
        Barcode: "6901234567890",
    }
    
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(product)
}

func main() {
    http.HandleFunc("/api/products/scan", productHandler)
    http.ListenAndServe(":8080", nil)
}

硬件集成(Go的优势领域):

// 扫码枪集成示例
package main

import (
    "fmt"
    "github.com/tarm/serial"
)

func readBarcodeScanner() {
    c := &serial.Config{
        Name: "COM3",
        Baud: 9600,
    }
    
    s, err := serial.OpenPort(c)
    if err != nil {
        panic(err)
    }
    
    buf := make([]byte, 128)
    for {
        n, err := s.Read(buf)
        if err != nil {
            break
        }
        barcode := string(buf[:n])
        fmt.Printf("扫描到条码: %s\n", barcode)
    }
}

2. 完整技术栈建议

方案一:Go后端 + Web前端(推荐)

// Go后端API服务
package main

import (
    "github.com/gin-gonic/gin"
    "github.com/jmoiron/sqlx"
    _ "github.com/lib/pq"
)

type Transaction struct {
    ID        string  `json:"id" db:"id"`
    Total     float64 `json:"total" db:"total"`
    Payment   string  `json:"payment" db:"payment"`
    CreatedAt string  `json:"created_at" db:"created_at"`
}

func main() {
    r := gin.Default()
    
    // 交易API
    r.POST("/api/transactions", createTransaction)
    r.GET("/api/transactions/:id", getTransaction)
    
    // 库存API
    r.PUT("/api/inventory/update", updateInventory)
    
    r.Run(":8080")
}

func createTransaction(c *gin.Context) {
    var transaction Transaction
    if err := c.ShouldBindJSON(&transaction); err != nil {
        c.JSON(400, gin.H{"error": err.Error()})
        return
    }
    
    // 处理交易逻辑
    db := sqlx.MustConnect("postgres", "user=pos dbname=pos sslmode=disable")
    _, err := db.NamedExec(
        `INSERT INTO transactions (id, total, payment) 
         VALUES (:id, :total, :payment)`,
        transaction,
    )
    
    if err != nil {
        c.JSON(500, gin.H{"error": "交易失败"})
        return
    }
    
    c.JSON(200, gin.H{"status": "success", "transaction_id": transaction.ID})
}

前端技术选择:

  • React/Vue.js:构建响应式Web界面
  • Electron:打包为桌面应用
  • PWA:支持离线操作的渐进式Web应用

方案二:混合架构

// 微服务拆分示例
// 商品服务
go run product-service/main.go --port=8081

// 交易服务  
go run transaction-service/main.go --port=8082

// 库存服务
go run inventory-service/main.go --port=8083

// API网关
package main

import (
    "github.com/gin-gonic/gin"
    "github.com/go-resty/resty/v2"
)

func main() {
    r := gin.Default()
    client := resty.New()
    
    // 网关路由
    r.POST("/api/checkout", func(c *gin.Context) {
        // 调用商品服务
        productResp, _ := client.R().
            SetBody(c.Request.Body).
            Post("http://localhost:8081/api/validate")
        
        // 调用交易服务
        transactionResp, _ := client.R().
            SetBody(productResp.Body()).
            Post("http://localhost:8082/api/create")
            
        c.JSON(200, transactionResp.Body())
    })
    
    r.Run(":8080")
}

3. 数据库选择

// PostgreSQL集成
package main

import (
    "database/sql"
    "fmt"
    _ "github.com/lib/pq"
)

func setupDatabase() {
    connStr := "user=pos dbname=point_of_sale sslmode=disable"
    db, err := sql.Open("postgres", connStr)
    
    // 创建交易表
    _, err = db.Exec(`
        CREATE TABLE IF NOT EXISTS transactions (
            id UUID PRIMARY KEY,
            total DECIMAL(10,2),
            payment_method VARCHAR(50),
            items JSONB,
            created_at TIMESTAMP DEFAULT NOW()
        )
    `)
    
    // 创建库存表
    _, err = db.Exec(`
        CREATE TABLE IF NOT EXISTS inventory (
            barcode VARCHAR(50) PRIMARY KEY,
            name VARCHAR(100),
            price DECIMAL(10,2),
            stock INTEGER,
            last_updated TIMESTAMP
        )
    `)
}

4. 关键考虑因素

并发处理(Go的优势):

// 并发处理多个收银台
package main

import (
    "sync"
    "time"
)

type Cashier struct {
    ID     int
    Queue  chan Transaction
}

func (c *Cashier) ProcessTransactions() {
    for txn := range c.Queue {
        // 处理交易
        processTransaction(txn)
    }
}

func main() {
    cashiers := make([]Cashier, 5)
    var wg sync.WaitGroup
    
    for i := range cashiers {
        cashiers[i].ID = i + 1
        cashiers[i].Queue = make(chan Transaction, 10)
        wg.Add(1)
        go func(c *Cashier) {
            defer wg.Done()
            c.ProcessTransactions()
        }(&cashiers[i])
    }
}

硬件设备集成:

  • 扫码枪:通过串口或USB HID
  • 钱箱:通过GPIO或串口控制
  • 票据打印机:ESC/POS指令集
  • 顾客显示屏:串口通信

5. 部署架构

负载均衡器
    |
    v
[API网关 (Go)] 
    |
    +----------------+----------------+
    |                |                |
    v                v                v
[商品服务]     [交易服务]       [库存服务]
    (Go)           (Go)            (Go)
    |                |                |
    +----------------+----------------+
                    |
                    v
              [数据库集群]
           (PostgreSQL/Redis)

Go语言适合构建POS系统的后端服务和微服务架构,但UI层建议使用Web技术。这种组合既能利用Go的高并发性能和硬件集成能力,又能获得现代Web UI的开发体验和跨平台支持。

回到顶部