亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

澆注接口到混凝土型 - 型開關

澆注接口到混凝土型 - 型開關

Go
森林海 2022-08-09 20:16:46
我正在尋找一種方法將接口轉換為具體類型以節省大量源代碼。初始情況是 Web 服務器處理程序的兩個函數。它們的不同之處僅在于一個函數解碼結構數組,另一個函數解碼單個結構并將其存儲在數據庫中。必須調用以進行保存的函數是相同的,具體取決于類型。若要確定是傳遞數組還是結構,請嘗試將接口轉換為類型,然后將其作為函數的參數相應地傳遞。與文檔和堆棧溢出帖子中描述的類似。但是,我沒有按預期獲得具體類型,并且程序始終運行到默認部分。我做錯了什么,或者我沒有考慮到什么?這些是默認部分的輸出:# interface is a struct... or a single repository struct: map[string]interface{}# interface is an array of structs... or a single repository struct: []interface{}以下是帶有函數的源代碼func (rh *RouteHandler) AddOrUpdateRepository(rw http.ResponseWriter, req *http.Request) {    repository := new(types.Repository)    rh.addOrUpdateRepositories(rw, req, repository)}func (rh *RouteHandler) AddOrUpdateRepositories(rw http.ResponseWriter, req *http.Request) {    repositories := make([]*types.Repository, 0)    rh.addOrUpdateRepositories(rw, req, repositories)}func (rh *RouteHandler) addOrUpdateRepositories(rw http.ResponseWriter, req *http.Request, v interface{}) {    defer req.Body.Close()    switch req.Header.Get("Content-Type") {    case "application/xml":        xmlDecoder := xml.NewDecoder(req.Body)        err := xmlDecoder.Decode(&v)        if err != nil {            rw.WriteHeader(http.StatusInternalServerError)            fmt.Fprintf(rw, "Failed to decode repositories or repository")            rh.ulogger.Error("Failed to decode repositories or repository: %v", err)            return        }    case "application/json":        fallthrough    default:        jsonDecoder := json.NewDecoder(req.Body)        err := jsonDecoder.Decode(&v)        if err != nil {            rw.WriteHeader(http.StatusInternalServerError)            fmt.Fprintf(rw, "Failed to decode repositories or repository")            rh.ulogger.Error("Failed to decode repositories or repository: %v", err)            return        }    }    var err error    switch x := v.(type) {    case map[string]*types.Repository:        for _, repository := range x {            err = rh.manager.AddOrUpdateRepository(context.Background(), repository)        }   
查看完整描述

1 回答

?
RISEBY

TA貢獻1856條經驗 獲得超5個贊

(稍微簡化一下。


您有一個具有以下簽名的函數:


func addOrUpdateRepositories(v interface{})

然后你這樣稱呼它:


repository := new(types.Repository)

addOrUpdateRepositories(repository)

就像這樣:


repositories := make([]*types.Repository, 0)

addOrUpdateRepositories(repositories)

在第一次調用中,存儲的值的具體類型將是(作為返回指向分配值的指針),在第二次調用中,存儲的值的具體類型將是 - 因為這是被告知要創建的內容。v*types.Repositorynewv[]*types.Repositorymake


現在,您在 上執行類型開關,其內容為:v


switch x := v.(type) {

case map[string]*types.Repository:

case map[string][]*types.Repository:

case nil:

default:

}

撇開以下情況不談:如果您不將其稱為傳遞 a,則不會在問題的代碼段中發生,則 將始終選擇默認分支,因為存儲在 中的具體值的類型是 never 或 。addOrUpdateRepositoriesnilvswitchvmap[string]*types.Repositorymap[string][]*types.Repository


我不確定為什么你沒有看到這一點,所以也許你應該完善你的問題,或者可能試圖在評論我的答案時澄清你的困惑?


另一個黑暗中的鏡頭:類型轉換(請注意,Go沒有類型轉換,正如@Flimzy指出的那樣)和Go中的類型切換實際上并沒有改變它們所操作的值的基礎表示形式 - 除了有限的一組(“每個人都期望如此”)情況,例如類型轉換為a到,這些情況被精確地記錄下來。float64int64


因此,您不能獲取一個(指向類型值的一部分指針)并以某種方式強制它“成為”:由于多種原因,這將是一件荒謬的事情,最明顯的是:如果您正在編寫Go編譯器,您將如何執行這樣的“類型轉換”?假設您真的要分配一個地圖,但是應該為該地圖中的哪個鍵分配原始(源)切片?將 a 類型轉換為 ?[]*types.Repositorytypes.Repositorymap[string][]*types.Repository[]*types.Repositorystruct {foo []*types.Repository; bar []*types.Repository}


查看完整回答
反對 回復 2022-08-09
  • 1 回答
  • 0 關注
  • 94 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號