如何在两个不同终端运行Golang文件

如何在两个不同终端运行Golang文件 我实现了一个简单的钱包间交易功能,想要从第一个终端执行交易(从A向B转账),同时从第二个终端检查B钱包的余额。但问题是当我同时运行两个终端时,第二个终端会一直等待第一个终端执行完成。

3 回复

已解决

更多关于如何在两个不同终端运行Golang文件的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


能分享一下你的解决方案吗?是让每个终端作为独立的goroutine运行,还是采用了其他方法?

在Golang中实现跨终端通信需要采用进程间通信(IPC)机制。以下是几种解决方案:

1. 使用文件锁(File Locking)

// 余额检查端
package main

import (
    "fmt"
    "os"
    "syscall"
    "time"
)

func checkBalance() {
    file, err := os.OpenFile("balance.lock", os.O_CREATE|os.O_RDWR, 0644)
    if err != nil {
        panic(err)
    }
    defer file.Close()
    
    // 非阻塞文件锁
    err = syscall.Flock(int(file.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
    if err != nil {
        fmt.Println("等待交易完成...")
        // 等待锁释放
        syscall.Flock(int(file.Fd()), syscall.LOCK_EX)
    }
    
    // 读取余额
    balance := readBalance()
    fmt.Printf("B钱包余额: %d\n", balance)
    
    syscall.Flock(int(file.Fd()), syscall.LOCK_UN)
}

func readBalance() int {
    // 实现读取余额逻辑
    return 100
}

2. 使用网络Socket通信

// 交易执行端
package main

import (
    "fmt"
    "net"
    "time"
)

func executeTransaction() {
    // 先通知余额检查端
    conn, err := net.Dial("tcp", "localhost:8080")
    if err != nil {
        fmt.Println("余额检查端未启动")
        return
    }
    defer conn.Close()
    
    // 发送交易开始信号
    conn.Write([]byte("TRANSACTION_START"))
    
    // 执行交易逻辑
    fmt.Println("执行A向B转账...")
    time.Sleep(2 * time.Second)
    
    // 发送交易完成信号
    conn.Write([]byte("TRANSACTION_END"))
}

// 余额检查端
func balanceChecker() {
    ln, err := net.Listen("tcp", ":8080")
    if err != nil {
        panic(err)
    }
    defer ln.Close()
    
    for {
        conn, err := ln.Accept()
        if err != nil {
            continue
        }
        
        go handleConnection(conn)
    }
}

func handleConnection(conn net.Conn) {
    defer conn.Close()
    
    buffer := make([]byte, 1024)
    n, err := conn.Read(buffer)
    if err != nil {
        return
    }
    
    message := string(buffer[:n])
    if message == "TRANSACTION_START" {
        fmt.Println("检测到交易开始,等待完成...")
        // 等待交易完成
        n, err = conn.Read(buffer)
        if err == nil && string(buffer[:n]) == "TRANSACTION_END" {
            fmt.Println("交易完成,当前余额:", getCurrentBalance())
        }
    }
}

func getCurrentBalance() int {
    return 150
}

3. 使用共享内存+信号量

// 共享状态管理
package main

import (
    "fmt"
    "sync"
    "time"
)

var (
    transactionInProgress bool
    mutex sync.RWMutex
)

// 交易执行端
func performTransaction() {
    mutex.Lock()
    transactionInProgress = true
    mutex.Unlock()
    
    defer func() {
        mutex.Lock()
        transactionInProgress = false
        mutex.Unlock()
    }()
    
    fmt.Println("执行转账交易...")
    time.Sleep(3 * time.Second)
    fmt.Println("交易完成")
}

// 余额检查端
func checkBalanceWithWait() {
    for {
        mutex.RLock()
        inProgress := transactionInProgress
        mutex.RUnlock()
        
        if !inProgress {
            break
        }
        fmt.Println("交易进行中,等待...")
        time.Sleep(500 * time.Millisecond)
    }
    
    fmt.Printf("B钱包余额: %d\n", readWalletBalance())
}

func readWalletBalance() int {
    return 200
}

4. 使用Channel通信(推荐)

// 主服务端
package main

import (
    "fmt"
    "net/http"
    "sync"
    "time"
)

var (
    balance     = 1000
    balanceLock sync.RWMutex
    transactionChan = make(chan bool, 1)
)

func main() {
    http.HandleFunc("/transfer", handleTransfer)
    http.HandleFunc("/balance", handleBalanceCheck)
    go processTransactions()
    http.ListenAndServe(":9090", nil)
}

func handleTransfer(w http.ResponseWriter, r *http.Request) {
    transactionChan <- true
    fmt.Fprintf(w, "交易请求已接收")
}

func handleBalanceCheck(w http.ResponseWriter, r *http.Request) {
    balanceLock.RLock()
    defer balanceLock.RUnlock()
    fmt.Fprintf(w, "当前余额: %d", balance)
}

func processTransactions() {
    for range transactionChan {
        balanceLock.Lock()
        fmt.Println("开始交易处理...")
        time.Sleep(2 * time.Second)
        balance += 100 // 模拟余额更新
        fmt.Println("交易处理完成")
        balanceLock.Unlock()
    }
}

使用示例:

# 终端1: 启动服务
go run main.go

# 终端2: 检查余额
curl http://localhost:9090/balance

# 终端3: 执行交易
curl http://localhost:9090/transfer

推荐使用第4种HTTP服务的方式,它提供了最好的跨终端兼容性和可扩展性。

回到顶部