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、使用简单,设计也简单;