這隻又跑出來了XD
Ring其實就是雙向環鏈(circular doubled linked list)
用這圖, 是想表達, 我們有一個歌單
可以單向依序放到完, 當然也能選擇循環依序播放阿 !!!
Ring可以滿足這行為的操作!!
只有一個Value屬性,開發者可以任意操作.
prev, next都是給操作方法操作用的.
type Ring struct {
next, prev *Ring
Value interface{}
}
可以發現Ring的結構跟List超像.
// New creates a ring of n elements.
func New(n int) *Ring {
if n <= 0 {
return nil
}
r := new(Ring)
p := r
for i := 1; i < n; i++ {
p.next = &Ring{prev: p}
p = p.next
}
p.next = r
r.prev = p
return r
}
func (r *Ring) init() *Ring {
r.next = r
r.prev = r
return r
}
var ring變數 ring.Ring
func (r *Ring) Next() *Ring {...}
func (r *Ring) Prev() *Ring {...}
func (r *Ring) Move(n int) *Ring {...}
func (r *Ring) Link(s *Ring) *Ring {...}
func (r *Ring) Unlink(n int) *Ring {...}
func (r *Ring) Len() int {...}
func (r *Ring) Do(f func(interface{})) {...}
package main
import (
"container/ring"
"fmt"
)
// 宣告一個要給Do()執行的函數, 用來列印值而已
var printRing = func(v interface{}) {
fmt.Print(v.(int), "->")
}
// 只是用來呼叫r.Do跟代入printRing, 只是多一個換行
func PrintRing(r *ring.Ring) {
r.Do(printRing)
fmt.Println()
}
func main() {
// 透過var 來宣告ring
var varRing ring.Ring
// 查看透過var宣告的ring的長度
fmt.Println("查看透過var宣告的ring的長度: ", varRing.Len())
fmt.Println("----------------------")
//透過New創建10個元素的ring
r := ring.New(10)
// 查看透過New()初始化ring的長度
fmt.Println("查看透過New()初始化ring的長度: ", r.Len())
// 給ring中每個元素進行走訪並且給值
for i := 0; i < 10; i++ {
r.Value = i
// 取得下一個元素
r = r.Next()
}
fmt.Print("r : ")
PrintRing(r)
// 往後移動ring的指向
r = r.Move(2)
fmt.Println("ring 向後移動2個位置的元素值:", r.Value)
// 往前移動ring的指向
r = r.Move(-8)
fmt.Println("ring 向前移動8個位置的元素值:", r.Value)
// 從ring當前指向開始刪除n個元素
deletedElm := r.Unlink(2)
fmt.Print("r 所剩下的元素 : ")
PrintRing(r)
fmt.Print("從r刪除的元素 : ")
PrintRing(deletedElm)
// 準備第2個ring r2
r2 := ring.New(3)
for i := 0; i < 3; i++ {
r2.Value = i + 10
r2 = r2.Next()
}
fmt.Print("r2 : ")
PrintRing(r2)
fmt.Println("現在r的指向在 :", r.Value)
// Link r 跟 r2
fmt.Print("Link r 跟 r2 : ")
linkedRing := r.Link(r2)
PrintRing(r)
// 以原本r.Next()開始走訪
fmt.Print("以原本r.Next()開始走訪 : ")
PrintRing(linkedRing)
}
/*
查看透過var宣告的ring的長度: 1
----------------------
查看透過New()初始化ring的長度: 10
r : 0->1->2->3->4->5->6->7->8->9->
ring 向後移動2個位置的元素值: 2
ring 向前移動8個位置的元素值: 4
r 所剩下的元素 : 4->7->8->9->0->1->2->3->
從r刪除的元素 : 5->6->
r2 : 10->11->12->
現在r的指向在 : 4
Link r 跟 r2 : 4->10->11->12->7->8->9->0->1->2->3->
以原本r.Next()開始走訪 : 7->8->9->0->1->2->3->4->10->11->12->
*/
package main
import (
"container/ring"
"fmt"
"time"
)
// song類別
type song struct {
name string
artist string
length time.Duration
}
// 定義歌單
var (
songs = []song{
{
name: "Something Just Like This",
artist: "The Chainsmokers",
length: 247,
},
{
name: "Blame",
artist: "Calvin Harris",
length: 214,
},
{
name: "Wolves",
artist: "Selena Gomez",
length: 197,
},
{
name: "Sing You To Sleep",
artist: "Matt Cab",
length: 236,
},
}
)
func main() {
// 載入歌單
songList := ring.New(len(songs))
repeatedCnt := 0
for i := 0; i < songList.Len(); i++ {
songList.Value = songs[i]
songList = songList.Next()
}
// 開始播放
for {
if repeatedCnt == 1 {
break
}
songList.Do(func(v interface{}) {
time.Sleep((v.(song).length / 100) * time.Second) // 加速播放
fmt.Printf("現正播放%s, 演唱者為%s\n", v.(song).name, v.(song).artist)
})
repeatedCnt++
fmt.Printf("播放次數 : %d\n", repeatedCnt)
}
fmt.Println("播放完畢")
}
/*
現正播放Something Just Like This, 演唱者為The Chainsmokers
現正播放Blame, 演唱者為Calvin Harris
現正播放Wolves, 演唱者為Selena Gomez
現正播放Sing You To Sleep, 演唱者為Matt Cab
播放次數 1:
現正播放Something Just Like This, 演唱者為The Chainsmokers
現正播放Blame, 演唱者為Calvin Harris
現正播放Wolves, 演唱者為Selena Gomez
現正播放Sing You To Sleep, 演唱者為Matt Cab
播放次數 2:
現正播放Something Just Like This, 演唱者為The Chainsmokers
現正播放Blame, 演唱者為Calvin Harris
現正播放Wolves, 演唱者為Selena Gomez
現正播放Sing You To Sleep, 演唱者為Matt Cab
播放次數 3:
播放完畢
*/
應該還有更多, 我暫時還沒想到, 歡迎大家補充給我.
感謝各位.