go语言自学实现项目(实战代码项目学)
go语言自学实现项目(实战代码项目学)func handleLibCommand(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 handleLibCommands(tokens []string) { switch tokens[1] { case "list": // 列举所有列表 for i:=0; i<
需求规划- 目标
设计实现一个简单的播放器。
- 调用方式
命令行调用
- 主要功能
- 查看、添加和删除里面的音乐曲目
- 播放音乐
- 支持 MP3 和 WAV
- 可扩展更多音频格式
- 退出程序
- 程序结构
全部源码在 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 <name><artist><source><type> -- 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<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(&mlib.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("Unrecognized lib command:" tokens[1])
}
}
当是 play 命令时,通过解析参数,来执行播放操作
func handleLibCommand(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)
}
增删改查逻辑
增删改查逻辑是由 mlib.MusicManager 来实现的。它的组成内容包括 2 部分:
- 成员变量
- 成员方法
成员变量中包含了一个 MusicEntry 类型的变量
musics []MusicEntry
MusicEntry 中记录了歌曲的一些基本信息。
type MusicEntry struct {
Id string
Name string
Artist string
Source string
Type 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 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(100 * time.Microsecond)
fmt.Println(".")
p.progress = 10
}
fmt.Println("\n Finished playing" source)
}
package mp
import (
"fmt"
"time"
)
type WAVPlayer struct {
stat int
progress int
}
func (w *WAVPlayer) Play(source string) {
fmt.Println("Playing WAV music" source)
w.progress = 0
for w.progress < 100 {
time.Sleep(100 * time.Microsecond)
fmt.Println(".")
w.progress = 10
}
fmt.Println("\n Finished playing" source)
}
在 mp.Play 中 Player 类型变量调用 Play 函数时,就会根据设定类型执行。
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)
}
构建执行
构建的过程使用 go run 执行:
go run mplayer.go
期间会出现命令行交互窗口,提示按照指定的命令格式来操作播放。
经过以上过程,一个基础版的音乐播放器完整开发完毕。