GO语言(六)接口使用
<music>
|------<src>
|-------<library>
|-------manager.go
|-------manager_test.go
|-------<play>
|-------play.go
|-------mp3.go
|-------wav.go
|--------<music>
|-------mplayer.go
|------<pkg>
|------<bin>
------------------------------------------------------------------------------------
library:音乐库文件所在目录
[manager.go]
1 package library 2 3 import "errors" 4 5 type MusicEntry struct { 6 Id string 7 Name string 8 Artist string 9 Source string 10 Type string 11 } 12 13 type MusicManager struct { 14 musics []MusicEntry 15 } 16 17 func NewMusicManager() *MusicManager { 18 return &MusicManager{make([]MusicEntry, 0)} 19 } 20 21 func (m *MusicManager) Len() int { 22 return len(m.musics) 23 } 24 25 func (m *MusicManager) Get(index int) (music *MusicEntry, err error) { 26 if index <0 || index >= len(m.musics) { 27 return nil, errors.New("Index out of range.") 28 } 29 return &m.musics[index], nil 30 } 31 32 func (m *MusicManager) Find(name string) *MusicEntry { 33 if len(m.musics)==0 { 34 return nil 35 } 36 37 for _,mm := range m.musics { 38 if mm.Name == name { 39 return &mm 40 } 41 } 42 return nil 43 } 44 45 func (m *MusicManager)Add(music *MusicEntry) { 46 m.musics = append(m.musics, *music) 47 } 48 49 func (m *MusicManager)Remove(index int) *MusicEntry { 50 if index<0 || index >= len(m.musics) { 51 return nil 52 } 53 54 removedMusic := &m.musics[index] 55 56 if index < len(m.musics)-1 { 57 m.musics = append(m.musics[:index-1], m.musics[index+1:]...) 58 } else if index ==0 { 59 m.musics = make([]MusicEntry, 0) 60 }else { 61 m.musics = m.musics[:index-1] 62 } 63 return removedMusic 64 }
[manager_test.go]
1 package library 2 3 import ( 4 "testing" 5 ) 6 7 func TestOps(t *testing.T) { 8 mm := NewMusicManager() 9 if mm == nil { 10 t.Error("NewMusicManager() failed.") 11 } 12 m0 := &MusicEntry {"1", "Cellion Dion", "My Heart Will Go On", "http://qbox.me/24501234", "MP3" } 13 mm.Add(m0) 14 15 if mm.Len() != 1 { 16 t.Error("MusicManager.Add() failed.") 17 } 18 19 m := mm.Find(m0.Name) 20 21 if m == nil { 22 t.Error("MusicManager.Find() failed.") 23 } 24 25 if m.Id != m0.Id || m.Artist != m0.Artist || m.Name != m0.Name || m.Source != m0.Source || m.Type != m0.Type { 26 t.Error("MusicManager.Find() failed. Found item mismatch.") 27 } 28 29 m, err := mm.Get(0) 30 31 if m == nil { 32 t.Error("MusicManager.Get() failed.", err) 33 } 34 35 m = mm.Remove(0) 36 if m == nil || mm.Len() != 0 { 37 t.Error("MusicManager.Remove() failed.", err) 38 } 39 }
play:各种音乐类型存放库
[play.go]
1 package play 2 3 import "fmt" 4 5 type Player interface { 6 Play(source string) 7 } 8 9 func Play(source, mtype string) { 10 var p Player 11 switch mtype { 12 case "MP3": 13 p = &MP3Player{} 14 case "WAV": 15 p = &WAVPlayer{} 16 default: 17 fmt.Println("Unsupported music type", mtype) 18 return 19 } 20 p.Play(source) 21 }
[mp3.go]
1 package play 2 3 import ( 4 "fmt" 5 "time" 6 ) 7 8 type MP3Player struct { 9 stat int 10 progress int 11 } 12 13 func (p *MP3Player)Play(source string) { 14 fmt.Println("Playing MP3 music", source) 15 16 p.progress = 0 17 18 for p.progress < 100 { 19 time.Sleep(100*time.Millisecond) 20 fmt.Print(".") 21 p.progress += 1 22 } 23 24 fmt.Println("\nFinished playing", source) 25 }
[wav.go]
1 package play 2 3 import ( 4 "fmt" 5 "time" 6 ) 7 8 type WAVPlayer struct { 9 stat int 10 progress int 11 } 12 13 func (p *WAVPlayer) Play(source string) { 14 fmt.Println("Playing WAV music", source) 15 16 p.progress = 0 17 18 for p.progress < 100 { 19 time.Sleep(1000*time.Millisecond) 20 fmt.Print(".") 21 p.progress += 10 22 } 23 24 fmt.Println("\nFinished playing", source) 25 }
music:主程序的放在处
[mplayer.go]
1 package main 2 3 import ( 4 "bufio" 5 "fmt" 6 "os" 7 "strconv" 8 "strings" 9 "play" 10 "library" 11 ) 12 13 var lib *library.MusicManager 14 var id int = 1 15 var ctrl, signal chan int 16 17 func handleLibCommands(tokens []string) { 18 switch tokens[1] { 19 case "list" : 20 for i:=0; i<lib.Len(); i++ { 21 e,_ := lib.Get(i) 22 fmt.Println(i+1, ":", e.Name, e.Artist, e.Source, e.Type) 23 } 24 case "add": 25 if len(tokens) == 6 { 26 id++ 27 lib.Add(&library.MusicEntry{string(strconv.Itoa(id)),tokens[2],tokens[3],tokens[4],tokens[5]}) 28 }else { 29 fmt.Println("USAGE: library add <name><artist><source><type>") 30 } 31 case "remove": 32 if len(tokens) == 3 { 33 lib.Remove(3) // 有问题 34 } else { 35 fmt.Println("USAGE: library remove <name>") 36 } 37 default: 38 fmt.Println("Unrecongnized library command:", tokens[1]) 39 } 40 } 41 42 func handlePlayCommands(tokens []string) { 43 if len(tokens) != 2 { 44 fmt.Println("USAGE: play <name>") 45 return 46 } 47 48 e := lib.Find(tokens[1]) 49 50 if e == nil { 51 fmt.Println("The music", tokens[1], "does not exist.") 52 return 53 } 54 55 play.Play(e.Source, e.Type) 56 } 57 58 func main() { 59 fmt.Println(` 60 Enter following commands to control the player: 61 lib add <name><artist><source><type> 62 lib remove <name> 63 play <name> 64 `) 65 66 lib = library.NewMusicManager() 67 68 r := bufio.NewReader(os.Stdin) 69 70 for { 71 fmt.Println("Enter command->") 72 73 rawLine,_,_ := r.ReadLine() 74 75 line := string(rawLine) 76 77 if line == "q" || line == "e" { 78 break 79 } 80 81 tokens := strings.Split(line, " ") 82 83 if tokens[0] == "lib" { 84 handleLibCommands(tokens) 85 }else if tokens[0] == "play" { 86 handlePlayCommands(tokens) 87 }else { 88 fmt.Println("Unrecongnized command:", tokens[0]) 89 } 90 } 91 }
;之后,返回到music目录节点,执行如下命令:
go build library
go build play
go build music
go test library
go install library
go install play
go install music
--------------------------------------------------------------------
接口使用的感受:
1、类似于C++中虚基类的作用,作为一个消费者的接口,用于接收生产者设计的方法;
2、生产者设计也简单,只需要实现接口中的方法就算设计了接口【无需如C++的,还需要继承】;
3、使用简单,设计也简单;