#### 1
不好意思, 我之前所说关于interface compare 的问题, 我是记错了, 刚刚找到了以前的代码, 之前我所说的使用interface变量进行对比时, 可以帮你做深度内存对比(memcmp),可能是因为这段代码,golang 中的string类型被设计为值类型, 该类型进行比较时, 底层会帮你进行深度的内存比对, 当时不知道怎么想的就留下了那样的印象
```go
str := "loop"
str1 := "li loop"
str2 := fmt.Sprintf("%s %s", "li", str)
i3 := interface{}(str1)
i4 := interface{}(str2)
fmt.Println(i3 == i4)
```
#### 2
interface在进行比对时首先会进行类型比较, interface{}(int32(1)) == interface{}(int64(1)) 结果为false,如果类型相同在进行类型判断, 有些类型是不能进行比较的, 比如selice, map, 会直接panic, 之前是依赖那个印象进行推论, 跟您回答的所以那几个回答都不对,然后您之前说的那个返回error的问题做了实验确实是那样, 好坑, 作为interface返回之后type域有了值所以就!=nil了
#### 3
不过如果参考slice != nil的用法来看,我们都知道:
* slice 类型不支持比较
* slice 其实底层是这样一个结构体(这个也跟您讲的有问题,没记太清除)
```go
struct slice{
size_t cap ; // 从data(实际保存元素的buffer的指针, data地址不一定是申请内存块开始的位置)这个地址开始到申请的内存块结束的大小 / sizeof(TYPE)
size_t len ; // 保存的元素个数
TYPE *data ; // 实际保存元素的buffer的指针
}
```
* slice == nil 或者 slice != nil 都做了特殊处理其底层都是判断data == null 或者 data != null
而按照这个逻辑interface也应该有个特殊处理,然而没有,好坑
#### 4
谢谢您对我项目的关注
* 之前根您说的锁链表的方法, 是最近萌生出的想法, 没有实际去实现, 不好意思, 我尝试去实现了一下发现会有各种问题, 方法完全不可行,如下代码
```go
func _unlink(target *LinkNode) {
//1. 如果此时target的上一个节点正在unlink操作,并且已经获得该锁,那么将等待,等待结束后, target的上一个节点已经被改变,等待的这个锁没有意义
target.prev.mutex.Lock()
defer target.prev.mutex.Unlock()
if target.prev != target {
target.mutex.Lock()
defer target.mutex.Unlock()
}
if target.prev != target.next && target != target.next {
target.next.mutex.Lock()
defer target.next.mutex.Unlock()
}
target.prev.next = target.next
target.next.prev = target.prev
target.prev = target
target.next = target
}
```
* 关于您之前提到的一个竞态问题,确实是存在的, 想了一些解决方案
```go
//第一种,在进入修改模式后判断自己是否已经被删除,如果被删除则重新将这个CacheNode加入到CachePool
func del( cn *cacheNode){
_unlink(cn.prev, cn.next)
cn.prev = cn
cn.next = cn
}
func (cpp *Pool)SearchCacheBall(token string)(cacheBall *Ball, exist bool){
cpp.rwm.RLock()
defer cpp.rwm.RUnlock()
if cacheNode, ok := cpp.hash[token]; ok{
//进入修改模式
cpp.rwm.RUnlock()
cpp.rwm.Lock()
if cacheNode.next != cacheNode{
first(cpp.lru, cacheNode)
}else{
//如果cacheNode被删除, 那么将其重新加入到CachePool中
if len(cpp.hash) >= cpp.maxSize{
//如果CachePool已经满了,则删除池中最不常用的cacheNode
delete(cpp.hash, cpp.lru.prev.token)
del(cpp.lru.prev)
}
cpp.hash[cacheNode.token] = cacheNode
push(cpp.lru, cacheNode)
}
//推出修改模式
cpp.rwm.Unlock()
cpp.rwm.RLock()
exist = true
cacheBall = cacheNode.core
}
return
}
```
```go
//第二种直接改为互斥锁, 将读取map的操作加到互斥的代码块中
type Pool struct{
//同步锁
mx sync.Mutex
//用于lru算法, 双向循环链表
lru *cacheNode
//用于根据token找到对应cacheNode, hash表
hash map[string]*cacheNode
//cachePool的最大容量
maxSize int
}
func (cpp *Pool)SearchCacheBall(token string)(cacheBall *Ball, exist bool){
cpp.mx.Lock()
defer cpp.mx.Unlock()
if cacheNode, ok := cpp.hash[token]; ok{
first(cpp.lru, cacheNode)
exist = true
cacheBall = cacheNode.core
}
return
}
func (cpp *Pool)AppendCacheBall(token string, cacheBall *Ball){
cpp.mx.Lock()
defer cpp.mx.Unlock()
if len(cpp.hash) >= cpp.maxSize{
//如果CachePool已经满了,则删除池中最不常用的cacheNode
delete(cpp.hash, cpp.lru.prev.token)
del(cpp.lru.prev)
}
cacheNode := &cacheNode{
token: token,
core: cacheBall,
}
cpp.hash[token] = cacheNode
push(cpp.lru, cacheNode)
}
```
有疑问加站长微信联系(非本文作者))