Go语言音乐播放器
来源:云海天教程
时间:2023-01-14 14:52:05 264浏览 收藏
IT行业相对于一般传统行业,发展更新速度更快,一旦停止了学习,很快就会被行业所淘汰。所以我们需要踏踏实实的不断学习,精进自己的技术,尤其是初学者。今天golang学习网给大家整理了《Go语言音乐播放器》,聊聊接口,我们一起来看看吧!
结合前面所学的知识,本节我们将设计并实现了一个音乐播放器程序。这个程序只是用于演示 Go语言的特性,因此大家就不要期望能看到华丽的播放界面,听到优美的音乐。接下来我们会示范以下的关键流程:音乐库功能,使用者可以查看、添加和删除里面的音乐曲目;播放音乐;支持 MP3 和 WAV,但也能随时扩展以支持更多的音乐类型;退出程序。
由于 Go语言初始定位为高并发的服务器端程序,尚未在 GUI 的支持上花费大量的精力,而当前版本的 Go语言标准库中没有提供 GUI 相关的功能,也没有成熟的第三方界面库,因此不太适合开发 GUI 程序。
因此,这个程序仍然会是一个命令行程序,我们将其命名为 Simple Media Player(SMP)。该程序在运行后进入一个循环,用于监听命令输入的状态。该程序将接受以下命令。
音乐库管理命令:lib,包括 list/add/remove 命令。播放管理:play 命令,play 后带歌曲名参数。退出程序:q 命令。
音乐库
我们先来实现音乐库的管理模块,它管理的对象为音乐。每首音乐都包含以下信息:唯一的 ID;音乐名;艺术家名;音乐位置;音乐文件类型(MP3 和 WAV 等)。
下面我们先定义音乐的结构体,具体如下所示:
type Music struct { Id string Name string Artist string Source string Type string}然后开始实现这个音乐库管理类型,其中我们使用了一个数组切片作为基础存储结构,其他的操作其实都只是对这个数组切片的包装,代码如下所示。
//manager.gopackage libraryimport "errors"type MusicManager struct { musics []MusicEntry}func NewMusicManager() *MusicManager { return &MusicManager{make([]MusicEntry, 0)}}func (m *MusicManager) Len() int { return len(m.musics)}func (m *MusicManager) Get(index int) (music *MusicEntry, err error) { if index = len(m.musics) { return nil, errors.New("Index out of range.") } return &m.musics[index], nil}func (m *MusicManager) Find(name string) *MusicEntry { if len(m.musics) == 0 { return nil } for _, m := range m.musics { if m.Name == name { return &m } } return nil}func (m *MusicManager) Add(music *MusicEntry) { m.musics = append(m.musics, *music)}func (m *MusicManager) Remove(index int) *MusicEntry { if index = len(m.musics) { return nil } removedMusic := &m.musics[index] // 从数组切片中删除元素 if index 实现了这么重要的一个基础数据管理模块后,我们应该马上编写单元测试,而不是给自己借口说等将来有空的时候再补上。下面的代码实现了 MusicManager 类型的单元测试。
//manager_test.gopackage libraryimport ( "testing")func TestOps(t *testing.T) { mm := NewMusicManager() if mm == nil { t.Error("NewMusicManager failed.") } if mm.Len() != 0 { t.Error("NewMusicManager failed, not empty.") } m0 := &MusicEntry{ "1", "My Heart Will Go On", "Celion Dion", Pop, "http://qbox.me/24501234", MP3} mm.Add(m0) if mm.Len() != 1 { t.Error("MusicManager.Add() failed.") } m := mm.Find(m0.Name) if m == nil { t.Error("MusicManager.Find() failed.") } if m.Id != m0.Id || m.Artist != m0.Artist || m.Name != m0.Name || m.Genre != m0.Genre || m.Source != m0.Source || m.Type != m0.Type { t.Error("MusicManager.Find() failed. Found item mismatch.") } m, err := mm.Get(0) if m == nil { t.Error("MusicManager.Get() failed.", err) } m = mm.Remove(0) if m == nil || mm.Len() != 0 { t.Error("MusicManager.Remove() failed.", err) }}这个单元测试看起来似乎有些偷懒,但它基本上已经覆盖了 MusicManager 的所有功能,实际上也确实测出了 MusicManager 实现过程中的几个问题。因此,养成良好的单元测试习惯还是非常有价值的。
音乐播放
我们接下来设计和实现音乐播放模块。按我们之前设置的目标,音乐播放模块应该是很容易扩展的,不应该在每次增加一种新音乐文件类型支持时都就需要大幅调整代码。我们来设计一个简单但又足够通用的播放函数:func Play(source, mtype string)
这里没有直接将 MusicEntry 作为参数传入,这是因为 MusicEntry 包含了一些多余的信息。本着最小原则,我们只需要将真正需要的信息传入即可,即音乐文件的位置以及音乐的类型。下面我们设计一个简单的接口:
type Player interface {
Play(source string)
}
//play.gopackage mpimport "fmt"type Player interface { Play(source string)}func Play(source, mtype string) { var p Player switch mtype { case "MP3": p = &MP3Player{} case "WAV": p = &WAVPlayer{} default: fmt.Println("Unsupported music type", mtype) return } p.Play(source)}因为我们这个例子并不会真正实现多媒体文件的解码和播放过程,所以对于 MP3Player 和 WAVPlayer,我们只实现其中一个作为示例,代码如下所示。
//mp3.gopackage mpimport ( "fmt" "time")type MP3Player struct { stat int progress int}func (p *MP3Player)Play(source string) { fmt.Println("Playing MP3 music", source) p.progress = 0 for p.progress 当然,我们也应该对播放流程进行单元测试。因为单元测试比较简单,这里就不再列出完整的单元测试代码了。
主程序
核心模块已经设计和实现完毕,现在就该使用它们了。我们的主程序是一个命令行交互程序,用户可以通过输入命令来控制播放过程以及获取播放信息。因为主程序与面向对象关系不大,所以我们只是为了完整性而把源代码列在这里,但不作过多解释。在这里,我们可以顺便了解一下命令行交互程序在 Go语言中的常规实现方式。下面的代码实现了音乐播放器的主程序。
//mplayer.gopackage mainimport ( "bufio" "fmt" "os" "strconv" "strings" "pkg/mplayer/mlib" "pkg/mplayer/mp")var lib *library.MusicManagervar id int = 1var ctrl, signal chan intfunc handleLibCommands(tokens []string) { switch tokens[1] { case "list": for i := 0; i
-
250 收藏
-
462 收藏
-
394 收藏
-
256 收藏
-
282 收藏
-
233 收藏
-
322 收藏
-
181 收藏
-
316 收藏
-
244 收藏
-
300 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 507次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习