Go面向对象---音乐库案例

案例目的

   演示Go语言面向对象编程特性,设计音乐播放器程序,此程序仅仅只是演示面向对象特性。关键流程:

(1) 音乐库功能:使用者可以查看、添加和删除里面的音乐曲目;

(2)、播放音乐;

(3)、支持MP3和WAV,但也能随时扩展支持更多的音乐类型;

(4)、退出程序。

    程序主要接受以下命令

(1)、音乐库管理命令:lib,包括list/add/remove命令

(2)、播放管理:play命令,play后带歌曲名字

(3)、退户程序:q命令

案例代码

(1)、音乐库管理模块,管理对象为音乐。创建package mlib(实现entry.go manager.go manager_test.go),实现对音乐文件的管理。

entry.go  
package mlib
/*
**** 管理对象为音乐,定义音乐结构体类型
****
**** 音乐结构体:id,name,artist,source,type
**** 音乐id、音乐名、艺术家名、音乐位置、类型
 */

type MusicEntry struct {
	Id       string
	Name     string
	Artist   string
	Source   string
	Type     string
}
manager.go
package mlib

import (
	"errors"
)

type MusicManager struct {
	musics  []MusicEntry
}

//创建Music管理对象
func NewMusicManager() *MusicManager {
	a := make([]MusicEntry, 0)
	return &MusicManager{
		musics : a,
	}
}

//长度
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 || name == "" {
		return nil
	}
	//遍历查找
	for _, v := range m.musics {
		if v.Name == name {
			return &v
		}
	}
	//没找到
	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 > 0 && index < len(m.musics)-1 {  //中间元素
		m.musics = append(m.musics[:index-1], m.musics[index+1:]...)
	}else if index == 0 {  //删除仅有的一个元素
		m.musics = make([]MusicEntry, 0)
	}else { //删除最后一个元素
		m.musics = m.musics[:index-1]
	}

	//返回删除的元素
	return removedMusic
}

func (m *MusicManager) RemoveByName(name string) *MusicEntry {
	if len(m.musics) == 0 {
		return nil
	}

	for i, v := range m.musics {
		if v.Name == name {
			return m.Remove(i)
		}
	}

	return nil
}
manager_test.go
package mlib

import (
	"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{
		Id : "1",
		Name : "My Heart Will Go On",
		Artist : "Celion Dion",
		Source : "http://qbox.me/24501234",
		Type : "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.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)
	}
}

(2)、音乐播放模块(package mp:play.go、mp3.go、wav.go)

play.go
package mp

import (
	"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)
}
mp3.go
package mp

import (
	"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 < 100 {
		time.Sleep(time.Millisecond * 100)  //延时假装正在播放
		fmt.Print(".")

		p.progress += 10
	}

	fmt.Println("\nFinished playing", source)
}
wav.go
package mp

import (
	"fmt"
	"time"
)

type WAVPlayer struct {
	stat     int
	progress int
	signal   chan int
}

func (p *WAVPlayer) Play(source string) {

	fmt.Println("Playing wav music", source)

	p.progress = 0

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

(3)、主程序。(package main:mplayer.go)

mplayer.go
package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"

	"mplayer/mlib"
	"mplayer/mp"

)
//音乐管理模块  全局变量声明与赋值
var lib *mlib.MusicManager = mlib.NewMusicManager()
var id int = 1
var ctrl, signal chan int

//功能函数
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++
			m := &mlib.MusicEntry {
				strconv.Itoa(id),
				tokens[2],
				tokens[3],
				tokens[4],
				tokens[5],
			}
			lib.Add(m)
		} 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("Unrecognized lib command:")
	}
}

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)
}

//由 main 函数作为程序入口点启动
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 := 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" {
			handlePlayCommand(tokens)
		} else {
			fmt.Println("Unrecognized command:", tokens[0])
		}
	}
}

程序运行结果:


遗留问题

(1)、多任务 : 单任务程序,至少需要这么几个线程:用户界面、音乐播放和视频播放。  

(2)、控制播放

知识盲点

1、Go语言项目构建以及包的组织结构 环境变量和包组织目录结构

 GoROOT环境变量是Go语言的类库,编译器回去查找标准库函数。GOPATH环境变量,构建Go环境,src文件夹下面创建project,project下面可以创建各种自建package以及源文件。

2、标准库包:errors、log、strconv、bufio、os、strings

3、构建测试程序及运行

参考书籍:《Go语言编程》许式伟

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值