go语言实战_实战代码项目学 Go 语言:音乐播放器

需求规划

  • 目标

设计实现一个简单的播放器。

  • 调用方式

命令行调用

  • 主要功能
  1. 查看、添加和删除里面的音乐曲目
  2. 播放音乐
  3. 支持 MP3 和 WAV
  4. 可扩展更多音频格式
  5. 退出程序
  • 程序结构
aa249f7d5a4ae0363d266961e0721608.png

全部源码在 src 文件夹下,mplayer 里是主程序,mlib 中是对播放器的控制逻辑,mp 中是对播放操作的逻辑。

代码实现

在代码实现中,按照程序结构分为 3 个部分实现:

  • 主程序
  • 增删改查逻辑
  • 操作逻辑

主程序

在主程序中,主要的功能点有 1 个:

  • 命令行交互
func main()  {fmt.Println("Enter following commands to control the player:" +"lib list -- View the existing music lib lib add  -- Add a music to the music lib")lib = mlib.NewMusicManager()r := bufio.NewReader(os.Stdin) // 接收命令行输入for {fmt.Print("Enter command-> ")rawLine, _, _ := r.ReadLine() // 接收命令行输入line := string(rawLine)if line == "q" || line == "e" { // 解析命令break}tokens := strings.Split(line, " ")if tokens[0] == "lib" { // 解析命令handleLibCommands(tokens)} else if tokens[0] == "play" { // 解析命令handleLibCommand(tokens)} else { // 解析命令fmt.Println("Unrecognized command:", tokens[0])}}}

当是 lib 命令时,通过解析第 1 个参数,来确定下一步的增删改查。

func handleLibCommands(tokens []string)  {switch tokens[1] {case "list": // 列举所有列表for i:=0; i")}case "remove": // 删除一条if len(tokens) == 3 {//lib.RemoveByName(tokens[2])} else {fmt.Println("USAGE: lib remove ")}default:fmt.Println("Unrecognized lib command:", tokens[1])}}

当是 play 命令时,通过解析参数,来执行播放操作

func handleLibCommand(tokens []string) {if len(tokens) != 2 {fmt.Println("USAGE: play ")return}e := lib.Find(tokens[1])if e == nil {fmt.Println("The music", tokens[1], "does not exist.")return}mp.Play(e.Source, e.Type)}

增删改查逻辑

增删改查逻辑是由 mlib.MusicManager 来实现的。它的组成内容包括 2 部分:

  • 成员变量
  • 成员方法

成员变量中包含了一个 MusicEntry 类型的变量

musics []MusicEntry

MusicEntry 中记录了歌曲的一些基本信息。

type MusicEntry struct {Id stringName stringArtist stringSource stringType string}

成员方法中定义了一系列增删改查的方法:

func (m *MusicManager) Len() int {return len(m.musics)}func (m *MusicManager) Get(index int) (music *MusicEntry, err error) {if index < 0 || 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 < 0 || index >= len(m.musics) {return nil}removedMusic := &m.musics[index]m.musics = append(m.musics[:index], m.musics[index+1:]...)return removedMusic}

同时定义了 MusicManager 的构造函数,在其中初始化了 MusicEntry 变量为 0。

func NewMusicManager() *MusicManager {return &MusicManager{make([]MusicEntry, 0)}}

操作逻辑是由 mp.Play 实现的,mp.Play 中 Player 定义了一个接口 Play(source string)

type Player interface {Play(source string)}

mp.mp3 和 mp.wav 分别都完整的实现了 Player 的全部接口。因此,继承了 Player 。

package mpimport ("fmt""time")type MP3Player struct {stat intprogress int}func (p *MP3Player) Play(source string) {fmt.Println("Playing MP3 music", source)p.progress = 0for p.progress < 100 {time.Sleep(100 * time.Microsecond)fmt.Println(".")p.progress += 10}fmt.Println(" Finished playing", source)}
package mpimport ("fmt""time")type WAVPlayer struct {stat intprogress int}func (w *WAVPlayer) Play(source string) {fmt.Println("Playing WAV music", source)w.progress = 0for w.progress < 100 {time.Sleep(100 * time.Microsecond)fmt.Println(".")w.progress += 10}fmt.Println(" Finished playing", source)}

在 mp.Play 中 Player 类型变量调用 Play 函数时,就会根据设定类型执行。

package mpimport "fmt"type Player interface {Play(source string)}func Play(source, mtype string)  {var p Playerswitch mtype {    case "MP3":p = &MP3Player{}case "WAV":p = &WAVPlayer{}default:fmt.Println("Unsupported music type", mtype)return}p.Play(source)}

构建执行

构建的过程使用 go run 执行:

go run mplayer.go 

期间会出现命令行交互窗口,提示按照指定的命令格式来操作播放。

经过以上过程,一个基础版的音乐播放器完整开发完毕。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值