2016-09-22 61 views
0

我被下面的代碼片段中類型斷言相關的錯誤所困擾。我不知道我錯過了什麼。 (* DbIterator).Iterator和key:= itr.Key()。(* Key).Slice和value:= itr.Value()。(* Value)。片。我想知道是否有更好的方法來做到這一點,而無需在代碼庫中隨處輸入斷言,或者更好的設計模式來處理這種情況。代碼片段是更大代碼庫的一部分。我已經爲這個問題拉出了最相關的位。任何在這方面的幫助,非常感謝。Golang:類型斷言錯誤問題

package rocksdb 

import (
    "github.com/tecbot/gorocksdb" 
) 

func (s *RocksDB) GetCFIterator(cfHandler *gorocksdb.ColumnFamilyHandle) db.Iterator { 
    opt := gorocksdb.NewDefaultReadOptions() 
    opt.SetFillCache(true) 
    defer opt.Destroy() 
    return &DbIterator{s.DB.NewIteratorCF(opt, cfHandler)} 
} 

type DbIterator struct { 
    *gorocksdb.Iterator 
} 

type Key struct { 
    *gorocksdb.Slice 
} 

type Value struct { 
    *gorocksdb.Slice 
} 

func (iterator *DbIterator) Key() db.Keyer { 
    return &Key{iterator.Iterator.Key()} 
} 

func (iterator *DbIterator) Value() db.Valuer { 
    return &Value{iterator.Iterator.Value()} 
} 

type RocksDB struct { 
    DB *gorocksdb.DB 
} 

我有一個迭代符接口

package db 

import (
    "bytes" 
    "testing" 
) 

type Iterator interface { 
    Valid() bool 
    Next() 
    Close() 
    SeekToFirst() 
    SeekToLast() 
    Seek(key []byte) 
    Key() Keyer 
    Value() Valuer 
} 

type Keyer interface { 
} 

type Valuer interface { 
} 

func testIterator(t *testing.T, itr db.Iterator, expectedValues map[string][]byte) { 
    itrResults := make(map[string][]byte) 
    itr = itr.(*DbIterator).Iterator //Line 270 which the error throws 
    itr.SeekToFirst() 
    for ; itr.Valid(); itr.Next() { 
     key := itr.Key().(*Key).Slice 
     value := itr.Value().(*Value).Slice 
     k := makeCopy(key.Data()) 
     v := makeCopy(value.Data()) 
     itrResults[string(k)] = v 
    } 
    if len(itrResults) != len(expectedValues) { 
     t.Fatalf("Expected [%d] results from iterator, found [%d]", len(expectedValues), len(itrResults)) 
    } 
    for k, v := range expectedValues { 
     if !bytes.Equal(itrResults[k], v) { 
      t.Fatalf("Wrong value for key [%s]. Expected [%s], found [%s]", k, itrResults[k], v) 
     } 
    } 
} 

錯誤消息

github.com/hyperledger/fabric/core/db/rocksdb 
core/db/rocksdb/rocksdb_test.go:270: cannot use itr.(*DbIterator).Iterator (type *gorocksdb.Iterator) as type db.Iterator in assignment: 
*gorocksdb.Iterator does not implement db.Iterator (wrong type for Key method) 
have Key() *gorocksdb.Slice 
want Key() db.Keyer 

回答

1

問題是不是那種斷言,你要去打破,無論有因爲實例你使用不會實現該接口。這就是說你可以通過做到這一點來優雅地處理這件事;

itr, ok = itr.(*DbIterator) 
if !ok { 
    //try to recover 
} 

但是,是的,就像我說的,當你得到該代碼的itr類型是不是有什麼代碼期待所以它不會與期望的結果結束,你就必須做一些恢復/錯誤處理在這裏使它更好地工作,或者弄清楚你是如何得到錯誤類型的。

+0

謝謝!刪除itr中的迭代器(* DbIterator).Iterator修復了這個問題!但仍試圖理解爲什麼導致這個問題的原因... – Nik

+1

@Nik'itr'的類型是'* gorocksdb.Iterator',但斷言是爲'* DbIterator',因此它會引發錯誤,除非你稱這個版本爲bool,返回狀態。如果您不確定該類型,則希望使用返回2個參數的版本來檢查它。如果你知道這個類型,你可以基本上使用原始樣本中的版本。但是,如果這種類型不是你聲稱的那樣,那麼你會得到一個恐慌,它基本上與C#/ C世界中的'invalidcastexception'或其他事物一樣。 – evanmcdonnal

+0

感謝evan的解釋!我剛剛意識到我並不需要類型斷言,因爲它確實無法斷言和恐慌。正如你所指出的,我正在試圖弄清楚,錯誤類型是如何首先傳遞下來的 – Nik