我正在編寫一個API的客戶端。一種方法,posts
,返回一組用戶的帖子。在自己的地方乾燥了共同的領域
- 每篇文章是八種不同類型之一。顯然,一種「是 - 一種」關係。
- 帖子的許多字段,包括(其中包括)ID,URL和時間戳對於每種類型的帖子都是通用的。
- 每種類型的帖子都有其類型唯一的字段。例如,一個照片文章將有一個分辨率和一個標題。
在一種具有繼承性的語言中,我將抽象基類Post
,然後子類化,爲每種類型的帖子創建一個具體類。我會在基礎Post
,也許fromJson()
有一個構造函數或工廠方法,它需要一個JSON對象並提取所有的公共字段。然後我會覆蓋每個子類中的提取專用字段,確保調用基本實現來幹提取常用字段。
Go沒有繼承,但它有構成。我定義了一個具有所有公共字段的Post
結構,然後我爲每個類型都創建了一個結構,其中包含一個匿名Post
字段,以便它包含所有Post
字段。例如,
type PhotoPost struct {
Post // which contains: ID int; URL string; etc
Caption string
Height int
Width int
/// etc
}
我的目標之一是我希望讓我的客戶的用戶能夠輕鬆訪問郵政的公共字段。所以我絕對不想讓我寫的Posts()
方法返回interface{}
,因爲隨時有人想要得到所有帖子的ID,例如,他們將不得不做一個可怕的類型開關,這將是一個圖案一遍又一遍地讓我畏縮:
func GetIDs(posts []interface{}) []int {
var ids []int
for _, p := range posts {
switch p.(type) {
case PhotoPost:
ids = append(ids, p.(PhotoPost).ID)
//... repeat for the 7 other kinds of posts, and don't forget a default!
}
}
}
這太糟糕了。但我不能讓Posts
返回[]Post
,因爲那時需要更專門化的數據(對於像「給我所有來自該用戶帖子的照片字幕」這樣的用例),它不會在那裏(因爲在Go中,a PhotoPost
不是Post
,它有一個Post
及其字段。
目前,我考慮有Posts()
返回PostCollection,這將是一個結構,將這個樣子,這樣至少我將避免上述類型開關怪物:
type PostCollection struct {
PhotoPosts []PhotoPost
// ...repeat for the others
}
但用例「將所有帖子的所有ID都放到一個切片中」或類似的東西仍然非常麻煩。有人可以建議一種慣用的方式來處理這個問題嗎?最好是不需要反射的一個?
我一直在琢磨讓每個Post類型實現一個TypedPost
界面,返回自己的發帖PostData()
方法,但它並不像存在,除非我有兩個名爲和匿名類型的似乎很奇怪(匿名,所以我可以說somePhotoPost.ID
當我知道我有一個PhotoPost
想和someTypedPost.PostData().ID
,當我只知道我正在處理某種TypedPost
。然後我有Posts()
返回[]TypedPost
。有沒有一個更好的方法?