Golang中实现这个功能的简单方法有哪些

Golang中实现这个功能的简单方法有哪些 你好。

我找到了这个程序(GitHub - raitonoberu/sptlrx: 在终端中显示时间同步的歌词),它的功能完全符合我的需求,只不过……它是用在终端里的,而我想要让它在一个本地网页上运行。

我喜欢和我的家人朋友一起唱歌,我正在一个树莓派上搭建一个(差不多算是)高保真音响系统,使用 Mopidy 和 Qobuz。

所以,我想知道这是否可行,我的意思是,我需要学习什么才能让那个程序在一个本地网页上工作?我指的是让歌词显示在一个简单的本地网页上,不需要花哨的功能,就像在终端里那样。

我需要修改什么,在代码的哪个部分……进行修改?


更多关于Golang中实现这个功能的简单方法有哪些的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang中实现这个功能的简单方法有哪些的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


要实现将终端歌词显示功能迁移到本地网页,以下是几种Golang实现方案:

方案一:使用标准库net/http创建Web服务器

package main

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

type LyricsLine struct {
    Time  int    `json:"time"`
    Text  string `json:"text"`
}

var currentLyrics []LyricsLine
var currentIndex int

func lyricsHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Cache-Control", "no-cache")
    w.Header().Set("Connection", "keep-alive")
    
    flusher, ok := w.(http.Flusher)
    if !ok {
        http.Error(w, "Streaming unsupported", http.StatusInternalServerError)
        return
    }
    
    // 模拟歌词推送
    for {
        if currentIndex < len(currentLyrics) {
            fmt.Fprintf(w, "data: %s\n\n", currentLyrics[currentIndex].Text)
            flusher.Flush()
            currentIndex++
        }
        time.Sleep(2 * time.Second)
    }
}

func main() {
    // 初始化示例歌词数据
    currentLyrics = []LyricsLine{
        {Time: 0, Text: "第一行歌词"},
        {Time: 5, Text: "第二行歌词"},
        {Time: 10, Text: "第三行歌词"},
    }
    
    http.HandleFunc("/lyrics", lyricsHandler)
    http.Handle("/", http.FileServer(http.Dir("./static")))
    
    fmt.Println("服务器启动在 http://localhost:8080")
    http.ListenAndServe(":8080", nil)
}

方案二:使用WebSocket实时同步歌词

package main

import (
    "log"
    "net/http"
    "github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
    CheckOrigin: func(r *http.Request) bool {
        return true // 允许所有来源(仅限本地使用)
    },
}

func websocketHandler(w http.ResponseWriter, r *http.Request) {
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println("WebSocket升级失败:", err)
        return
    }
    defer conn.Close()
    
    // 从原程序获取歌词数据并发送
    for {
        // 这里需要集成原程序的歌词获取逻辑
        lyricsLine := getCurrentLyrics() // 假设的函数
        
        err := conn.WriteJSON(lyricsLine)
        if err != nil {
            log.Println("发送失败:", err)
            break
        }
    }
}

func getCurrentLyrics() map[string]interface{} {
    // 这里实现从原程序获取当前歌词的逻辑
    return map[string]interface{}{
        "text": "当前歌词",
        "time": 12345,
    }
}

func main() {
    http.HandleFunc("/ws", websocketHandler)
    http.Handle("/", http.FileServer(http.Dir("./web")))
    
    log.Println("服务器启动: http://localhost:8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

方案三:集成原程序的核心逻辑

package main

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

type LyricsServer struct {
    mu      sync.RWMutex
    lyrics  []string
    current string
    position time.Duration
}

func (ls *LyricsServer) updateLyrics() {
    // 这里需要修改原程序的歌词获取逻辑
    // 将原来的终端输出改为更新内部状态
    ls.mu.Lock()
    defer ls.mu.Unlock()
    
    // 模拟更新
    ls.current = "更新的歌词"
    ls.position = time.Second * 30
}

func (ls *LyricsServer) getCurrent() map[string]interface{} {
    ls.mu.RLock()
    defer ls.mu.RUnlock()
    
    return map[string]interface{}{
        "lyrics":  ls.current,
        "position": ls.position.Seconds(),
    }
}

func main() {
    server := &LyricsServer{}
    
    http.HandleFunc("/api/lyrics", func(w http.ResponseWriter, r *http.Request) {
        data := server.getCurrent()
        json.NewEncoder(w).Encode(data)
    })
    
    // 静态文件服务
    fs := http.FileServer(http.Dir("public"))
    http.Handle("/", fs)
    
    // 启动歌词更新循环
    go func() {
        ticker := time.NewTicker(100 * time.Millisecond)
        for range ticker.C {
            server.updateLyrics()
        }
    }()
    
    http.ListenAndServe(":8080", nil)
}

前端HTML示例(保存为static/index.html)

<!DOCTYPE html>
<html>
<head>
    <title>歌词显示</title>
    <style>
        #lyrics {
            font-size: 2em;
            text-align: center;
            margin-top: 20%;
            font-family: monospace;
        }
    </style>
</head>
<body>
    <div id="lyrics">等待歌词...</div>
    
    <script>
        // 使用EventSource
        const evtSource = new EventSource("/lyrics");
        
        evtSource.onmessage = function(event) {
            document.getElementById("lyrics").textContent = event.data;
        };
        
        evtSource.onerror = function() {
            console.log("连接错误");
        };
    </script>
</body>
</html>

需要修改原程序的部分:

  1. 数据输出层:将原程序的终端输出改为Web API输出
  2. 时间同步逻辑:保持原有的时间同步机制,改为通过HTTP或WebSocket发送
  3. 歌词解析:复用原有的歌词解析模块,只改变输出方式

关键修改点通常在:

  • 主循环中的显示部分
  • 时间同步回调函数
  • 歌词更新触发机制

将原有的fmt.Println或终端输出函数调用替换为向Web客户端发送数据的逻辑即可。

回到顶部