Проверка, имеет ли тип переменной ноль при использовании интерфейса - PullRequest
0 голосов
/ 08 апреля 2020

У меня есть этот интерфейс для объекта кэша, который отражает кэш lru из github.com/hashicorp/golang-lru:

type Cacher interface {
    Add(key, value interface{})
    Get(key interface{}) (value interface{}, ok bool)

}

В main.go Я создаю объект, когда выполняются некоторые условия, в противном случае он остается нулевым :

import lru "github.com/hashicorp/golang-lru"
...
var cache *lru.ARCCache
if someCondition {
    cache, _ = lru.NewARC(int(cacheSize))
}

... later on
r.Cache = cache

Теперь в другом пакете я проверяю, равен ли кэш нулю, прежде чем выполнять какие-либо операции с ним:

if r.Cache != nil {
    v, found := r.Cache.Get(...)
}

Это приводит к ошибке invalid memory address or nil pointer dereference потому что тип не ноль, а значение.

Мой вопрос заключается в том, как проверить, равен ли r.Cache ноль, без необходимости импортировать github.com/hashicorp/golang-lru в этот пакет (что делает использование Cacher интерфейс бессмысленный): if r.Cache != (*lru.ARCCache)(nil)

Ответы [ 2 ]

0 голосов
/ 08 апреля 2020

Просто знайте, что (*lru.ARCCache)(nil) != Cacher(nil).

Так что просто не присваивайте (*lru.ARCCache)(nil) r.Cache.

Вот исправление:

if cache != nil {
    r.Cache = cache
}
0 голосов
/ 08 апреля 2020

Избегайте проверки на нулевое конкретное значение в интерфейсе, потому что нулевое значение может быть допустимой реализацией интерфейса. Вот несколько надуманный пример, где nil является действительным:

type exampleCacher struct { }

func (c *exampleCacher) Get(key interface{}) (value interface{}, ok bool) }
   if c == nil {
      return nil, false
   }
   ...
}

Лучшим решением проблемы является обеспечение того, чтобы код назначал действительные значения только для r.Cache.

Код в вопрос всегда устанавливает r.Cache в ненулевое значение, потому что код назначает конкретный тип r.Cache. См. FAQ в nil error для объяснения.

Исправьте проблему, объявив cache как Cacher.

var cache Cacher

Как я упоминал в мой комментарий выше, еще одно исправление:

if cache != nil { 
   r.Cache = cache 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...