go学习笔记(6)——音乐播放器实现

声明:首先说明这个项目来自于许式伟的《Go语言编程》,书中也给出了详尽的源代码描述,不过代码中还是存在一些问题,首先说明一下所存在的问题

问题一:音乐的播放结构体中定义了五个属性字段,在后面赋值的时候又变成了六个字段的赋值

问题二:Play函数在调用的时候多传递了两个参数,在函数原型的时候只有两个参数

问题三:RemoveByName方法并没有实现

这两个问题应该都是为了后期更好的进行项目扩展,不过作为小白的我现在还是以学习和调通代码为主,再此基础上面在进行一步步的功能扩展,下面给出响应的项目说明和可以运行的实现基本功能的代码实现,所有的实现细节已经给出了详细的注释:

一:整体的逻辑框架


二:音乐库管理模块

》Len    求歌曲名长度

》Get    通过索引查找歌曲

》Find    通过名字查找歌曲

》Add    添加歌曲

》Remove    通过索引删除歌曲

》RemoveByName    通过歌名删除歌曲

package library

import (
	"errors"
	"fmt"
)

//定义音乐结构体
type MusicEntry struct {
	Id 	string		//音乐的唯一Id
	Name 	string		//音乐名
	Artist	string		//艺术家名
	Source	string		//音乐位置
	Type 	string		//音乐类型(MP3和WAV)
}

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 < 0 || index >= len(m.musics) {
		return nil, errors.New("Index out of range.")
	}
	return &m.musics[index], err
}

//通过对比名字查看要找的歌曲是否存在
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]
	//从数组切片中删除元素
	if index < len(m.musics) - 1 {	//中间元素
		m.musics = append(m.musics[:index - 1], m.musics[index + 1:]...)
	}
	return &removedMusic
}

//通过歌名删除歌曲
func (m *MusicManager) RemoveByName(name string) *MusicEntry {
	removedMusic := m.Find(name)
	if removedMusic == nil{
		fmt.Println("Want to delete the song does not exist")
		return nil
	}
	return removedMusic
}

二:音乐管理单元测试模块(go单元测试测试将在后面的学习过程在详细说明,现在只要知道测试的重要性即可)

package library

import "testing"

func TestOps(t *testing.T) {
	mm := NewMusicManager()    //新建管理测试
	if mm == nil {
		t.Error("NewManagerMusic faild")
	}

	if mm.Len() != 0 {    //len测试
		t.Error("NewManagerMusic faild, 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)    //find测试
	if m == nil {
		t.Error("MusicManager.Find() failed")
	}

	 if m.Id != m0.Id || m.Name != m0.Name || m.Artist != m0.Artist ||
		 m.Source != m0.Source || m.Type != m0.Type {
			t.Error("MusicManager.Find() failed. Find item mismatch")
	}

	m, err := mm.Get(0)    //get测试
	if m == nil {
		t.Error("MusicManager.Get() failed", err)
	}

	//空的时候直接进行测试会出问题
	m = mm.Remove(0)       //Remove测试
	if m == nil || mm.Len() != 0 {
		t.Error("MusicManager.Remove() failed", err)
	}
}

三:播放实现(播放包括的格式有MP3和WAV两种格式,当然再次也可以扩张使其支持其他格式的播放)

package mp

//音乐播放模块
import "fmt"

//设计一个简单的接口避免将MusicEntry中多余的信息传入
type Player interface {
	Play(Source string)
}

//播放实现,再此也可以在添加其他格式
func Play(Source, mtype string)  {
	var p Player

	switch mtype {
	case "MP3":		//MP3格式播放
		p = &MP3Player{}
	case "WAV":		//WAV格式播放
		p = &WAVPlayer{}
	default:
		fmt.Println("Unsupported music type", mtype)
		return
	}
	p.Play(Source)
}
package mp

import (
	"fmt"
	"time"
)

type MP3Player struct {
	stat 		int
	progress 	int
}

//MP3格式播放具体实现
func (p *MP3Player) Play(Source string) {
	fmt.Println("Playing MP3 music", Source)

	p.progress = 0

	for p.progress < 100 {
		time.Sleep(100 * time.Millisecond)		//假装正在播放
		fmt.Print(".")
		p.progress += 10
	}
	fmt.Println("\nFinished playing", Source)
}
package mp

import (
	"fmt"
	"time"
)

type MP3Player struct {
	stat 		int
	progress 	int
}

//MP3格式播放具体实现
func (p *MP3Player) Play(Source string) {
	fmt.Println("Playing MP3 music", Source)

	p.progress = 0

	for p.progress < 100 {
		time.Sleep(100 * time.Millisecond)		//假装正在播放
		fmt.Print(".")
		p.progress += 10
	}
	fmt.Println("\nFinished playing", Source)
}

四:主程序调用实现

package main

import (
	"goCode/src/music/library"
	"fmt"
	"strconv"
	"goCode/src/music/mp"
	"bufio"
	"os"
	"strings"
)

var lib *library.MusicManager
var id int = 1


//管理模块句柄实现
func handleLibCommands(tokens []string)  {
	switch tokens[1] {
	case "list":
		for i := 0; i < lib.Len(); i++ {
			e, _ := lib.Get(i)
			fmt.Println(i + 1, ":", e.Name, e.Artist, e.Source, e.Type)
		}
	case "add":
		if len(tokens) == 6 {
			id++
			lib.Add(&library.MusicEntry{strconv.Itoa(id),
			tokens[2], tokens[3], tokens[4], tokens[5]})
		}else {
			fmt.Println("USAGE: lib add <name><artist><source><type>")
		}
	case "remove":
		if len(tokens) == 3 {
			lib.RemoveByName(tokens[2])
		}else {
			fmt.Println("USAGE: lib remove <name>")
		}
	default:
		fmt.Println("Unrecognied lib commond:", tokens[1])
	}
}

//播放模块句柄实现
func handlePlayCommand(tokens []string)  {
	if len(tokens) != 2 {
		fmt.Println("USAGE: play <name>")
		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)
}

func main()  {
	//打印操作菜单
	fmt.Println(`
		Enter following commands to control the player:
		lib list -- View the existing music lib
		lib add <name><artist><source><type> -- Add a music to the music lib
		lib remove <name> -- Remove the specified music from the lib
		play <name> -- Play the specified music
	`)
	lib = library.NewMusicManager()

	r := bufio.NewReader(os.Stdin)

	for{
		fmt.Print("Enter Command-> ")

		rawLine, _, _ := r.ReadLine()
		line := string(rawLine)

		//输入q或者e时退出播放器
		if line == "q" || line == "e" {
			break
		}

		tokens := strings.Split(line, " ")
		if tokens[0] == "lib" {
			handleLibCommands(tokens)
		}else if tokens[0] == "play"{
			handlePlayCommand(tokens)
		}else {
			fmt.Println("Unrecognized command:", tokens[0])
		}
	}
}

五:演示


  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

double_happiness

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值