如何避免需要動態選擇類型的程式碼重複?
在編寫程式碼時,我們經常會遇到需要根據不同條件選擇不同類型的程式碼的情況。在這種情況下,如果沒有合適的處理方式,程式碼可能會變得冗長而重複。那麼,如何避免這種程式碼重複呢? php小編百草為大家帶來了一些簡單又有效的解決方案,讓我們一起來看看吧!
問題內容
以下程式碼是視訊串流解析器的簡化範例。輸入是包含視訊和音訊幀的二進位資料。每個框架由以下部分組成:
- 幀類型標誌,指示是視訊幀還是音訊幀
- 標題
- 有效負載
目標是解析流,從標頭和有效負載中提取欄位。
所以,第一種方法是:
package main import ( "fmt" "encoding/binary" "bytes" ) type Type byte const ( Video Type = 0xFC Audio Type = 0xFA ) var HMap = map[Type]string { Video: "Video", Audio: "Audio", } type CommonHeader struct { Type Type } type HeaderVideo struct { Width uint16 Height uint16 Length uint32 } type HeaderAudio struct { SampleRate uint16 Length uint16 } func main() { data := bytes.NewReader([]byte{0xFC, 0x80, 0x07, 0x38, 0x04, 0x02, 0x00, 0x00, 0x00, 0xFF, 0xAF, 0xFA, 0x10, 0x00, 0x01, 0x00, 0xFF}) var cHeader CommonHeader var dataLength int for { err := binary.Read(data, binary.LittleEndian, &cHeader) if err != nil { break } fmt.Println(HMap[cHeader.Type]) switch cHeader.Type { case Video: var info HeaderVideo binary.Read(data, binary.LittleEndian, &info) dataLength = int(info.Length) fmt.Println(info) case Audio: var info HeaderAudio binary.Read(data, binary.LittleEndian, &info) dataLength = int(info.Length) fmt.Println(info) } payload := make([]byte, dataLength) data.Read(payload) fmt.Println(payload) } }
它有效,但我不喜歡 switch
案例中的程式碼重複。本質上,我們必須重複相同的程式碼,只是因為幀類型不同。
嘗試避免重複的一種方法是:
package main import ( "fmt" "encoding/binary" "bytes" ) type Type byte const ( Video Type = 0xFC Audio Type = 0xFA ) var HMap = map[Type]string { Video: "Video", Audio: "Audio", } type CommonHeader struct { Type Type } type Header interface { GetLength() int } type HeaderVideo struct { Width uint16 Height uint16 Length uint32 } func (h HeaderVideo) GetLength() int { return int(h.Length) } type HeaderAudio struct { SampleRate uint16 Length uint16 } func (h HeaderAudio) GetLength() int { return int(h.Length) } var TMap = map[Type]func() Header { Video: func() Header { return &HeaderVideo{} }, Audio: func() Header { return &HeaderAudio{} }, } func main() { data := bytes.NewReader([]byte{0xFC, 0x80, 0x07, 0x38, 0x04, 0x02, 0x00, 0x00, 0x00, 0xFF, 0xAF, 0xFA, 0x10, 0x00, 0x01, 0x00, 0xFF}) var cHeader CommonHeader for { err := binary.Read(data, binary.LittleEndian, &cHeader) if err != nil { break } fmt.Println(HMap[cHeader.Type]) info := TMap[cHeader.Type]() binary.Read(data, binary.LittleEndian, info) fmt.Println(info) payload := make([]byte, info.GetLength()) data.Read(payload) fmt.Println(payload) } }
也就是說,我們透過引入 TMap
映射來實現動態類型選擇,該映射允許根據幀類型創建正確結構的實例。但是,此解決方案的代價是對每個幀類型重複 GetLength()
方法。
我覺得很令人不安的是,似乎沒有辦法完全避免重複。 我是否遺漏了什麼,還是只是語言的限制?
這是一個相關的問題(實際上是由同一個問題觸發的),但是,它的前提忽略了動態類型選擇的需要,因此公認的解決方案(使用泛型)沒有幫助。
解決方法
King 的答案要求對用於編碼長度的每個整數類型進行重複。 Mondarin 的答案 使用可怕的 reflect
套件。這是避免這兩個問題的解決方案。這個答案是基於國王的答案。
使用 GetLength() 方法宣告泛型類型。
type Length[T uint8 | uint16 | uint32 | uint64] struct { Length T } func (l Length[T]) GetLength() int { return int(l.Length) }
從每個標頭類型中刪除 GetLength 方法。在每個標頭類型中嵌入通用長度類型:
type HeaderVideo struct { Width uint16 Height uint16 Length[uint32] } type HeaderAudio struct { SampleRate uint16 Length[uint16] }
在問題中宣告 TMap
as。 GetLength
方法由嵌入欄位提供。
var TMap = map[Type]func() Header{ Video: func() Header { return &HeaderVideo{} }, Audio: func() Header { return &HeaderAudio{} }, }
https://www.php.cn/link/ceb9f6b8ffa77c49b6b4570ea19c76bf
#(與問題中的程式碼一樣,此答案透過binary.Read
函數間接使用reflect
套件。reflect
套件是保持程式碼乾燥的好工具。)
以上是如何避免需要動態選擇類型的程式碼重複?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

是的,H5頁面製作是前端開發的重要實現方式,涉及HTML、CSS和JavaScript等核心技術。開發者通過巧妙結合這些技術,例如使用<canvas>標籤繪製圖形或使用JavaScript控制交互行為,構建出動態且功能強大的H5頁面。

如何使用JavaScript或CSS控制瀏覽器打印設置中的頁首和頁尾在瀏覽器的打印設置中,有一個選項可以控制是否顯�...

關於inline-block元素錯位顯示的原因及解決方案在編寫網頁佈局時,我們常常會遇到一些看似奇怪的顯示問題。比...

如何實現分段器的45度曲線效果?在實現分段器的過程中,如何讓點擊左側按鈕時右側邊框變成45度曲線,而點�...

CSS自定義resize符號的方法與背景色統一在日常開發中,我們經常會遇到需要自定義用戶界面細節的情況,比如調...

實時比特幣美元價格 影響比特幣價格的因素 預測比特幣未來價格的指標 以下是 2018-2024 年比特幣價格的一些關鍵信息:
