执行命令:
go tool compile -S ./src/main.go
得到 main 函数的汇编命令,可以看到:r = c 这一行语句实际上是调用了 runtime.convI2I(SB),也就是 convI2I 函数,从函数名来看,就是将一个 interface 转换成另外一个 interface,看下它的源代码:
func convI2I(inter *interfacetype, i iface) (r iface) {
tab := i.tab
iftab == nil {
return
}
iftab.inter == inter {
r.tab = tab
r.data= i.data
return
}
r.tab = getitab(inter, tab._type, false)
r.data= i.data
return
}
首先先来看下dhcp协议,在dhcp协议中,定义了一个option字段,该字段主要是用来扩展dhcp协议的,option 60 (vendor class identifier)是dhcp报文中的一个选项字段,code为60,可以标识终端类型,根据不同的终端类型来选择接口下的网关。首先先来看下dhcp协议,在dhcp协议中,定义了一个option字段,该字段主要是用来扩展dhcp协议的,option 60 (vendor classidentifier)是dhcp报文中的一个选项字段,code为60,可以标识终端类型,根据不同的终端类型来选择接口下的网关。 、 、 、 、 begin 、end :获得容器首、尾迭代器 clear :将容器清空 empty :判断容器是否为空 size :得到容器元素个数 s1.swap s2 :将s1和s2两容器内容交换 相关数据类型(s表示容器类型) s::iterator:指向容器元素的迭代器类型 s::const_iterator:常迭代器类型 容 器 可逆容器、随机访问容器 可逆容器 s::reverse_iterator:逆向迭代器类型 s::const_reverse_iterator:逆向常迭代器类型 rbegin :指向容器尾的逆向迭代器 rend :指向容器首的逆向迭代器 随机访问容器 s[n]:获得容器s的第n个元素 * 容 器 * 顺序容器 顺序容器的接口 赋值 assign 插入函数 insert, push_front(只对list和deque), push_back 删除函数 erase,clear,pop_front(只对list和deque) ,pop_back 其他顺序容器访问函数 front,back 改变大小 resize 顺序容器 例10-4 * 顺序容器 //包含的头文件略去…… template void printcontainer const char* msg, const t& s cout msg ": "。
我们还知道,tab 是由接口类型 interfacetype 和 实体类型 _type。所以最关键的语句是 r.tab = getitab(inter, tab._type, false)。
因此,重点来看下 getitab 函数的源码,只看关键的地方:
funcgetitab(inter *interfacetype, typ *_type, canfail bool)*itab{
// ……
// 根据 inter, typ 计算出 hash 值
h := itabhash(inter, typ)
// look twice - once without lock, once with.
// common case will be no lock contention.
varm *itab
varlocked int
forlocked = 0; locked < 2; locked++ {
iflocked != 0{
lock(&ifaceLock)
}
// 遍历哈希表的一个 slot
form = (*itab)(atomic.Loadp(unsafe.Pointer(&hash[h]))); m != nil; m = m.link {
// 如果在 hash 表中已经找到了 itab(inter 和 typ 指针都相同)
ifm.inter == inter && m._type == typ {
// ……
iflocked != 0{
unlock(&ifaceLock)
}
returnm
}
}
}
// 在 hash 表中没有找到 itab,那么新生成一个 itab
replace unsafe characters with their escape sequences. unsafe characters are those characters that may be altered during transport across the internet, and include the (<, >, ", #, {, }, |, \, ^, ~, [, ], and ') characters. this flag applies to all urls, including opaque urls.。replace unsafe characters with their escape sequences. unsafe characters are those characters that may be altered during transport across the internet, and include the (<, >, ", #, {, }, |, \, ^, [, ], and ') characters. this flag applies to all urls, including opaque urls.。 private static final unsafe unsafe = util.getunsafe()。
m.inter = inter
m._type = typ
// 添加到全局的 hash 表中
additab(m, true, canfail)
unlock(&ifaceLock)
ifm.bad {
returnnil
}
returnm
}
8 查找结构:符号表,二叉查找树,二叉查找树的查找、插入和删除操作,avl树,高度平衡,ll, lr, rr, rl 旋转, 插入算法,时间复杂性分析,b树,m叉查找树,m叉查找树的查找,b树的定义和性质,b树的插入操作,b树的删除操作,静态散列,散列表,散列函数,溢出处理,开放寻址,链接。第8章 查找结构:符号表,二叉查找树,二叉查找树的查找、插入和删除操作,avl树,高度平衡,avl树的插入算法,avl树的时间复杂性分析,m叉查找树,m叉查找树的查找,b树的定义和性质,b树的插入操作,b树的删除操作,静态散列,散列表,散列函数,溢出处理。c++ stl(standard template library标准模板库)是通用类模板和算法的集合,它提供给程序员一些标准的数据结构的实现如queues(队列),lists(链表),和stacks(栈)等.c++stl提供给程序员以下三类数据结构的实现:标准容器类顺序性容器vector从后面快速的插入与删除,直接访问任何元素deque从前面或后面快速的插入与删除,直接访问任何元素list双链表,从任何地方快速插入与删除关联容器set快速查找,不允许重复值multiset快速查找,允许重复值map一对多映射,基于关键字快速查找,不允许重复值multimap一对多映射,基于关键字快速查找,允...。
这里查找了两次,并且第二次上锁了,这是因为如果第一次没找到,在第二次仍然没有找到相应的 itab 的情况下,需要新生成一个,并且写入哈希表,因此需要加锁。这样,其他协程在查找相同的 itab 并且也没有找到时,第二次查找时,会被挂住,之后,就会查到第一个协程写入哈希表的 itab。
再来看一下 additab 函数的代码:
// 检查 _type 是否符合 interface_type 并且创建对应的 itab 结构体 将其放到 hash 表中
funcadditab(m *itab, locked, canfail bool){
inter := m.inter
typ := m._type
x := typ.uncommon()
// both inter and typ have method sorted by name,
// and interface names are unique,
// so can iterate over both in lock step;
// the loop is O(ni+nt) not O(ni*nt).
//
// inter 和 typ 的方法都按方法名称进行了排序
// 并且方法名都是唯一的。所以循环的次数是固定的
// 只用循环 O(ni+nt),而非 O(ni*nt)
ni := len(inter.mhdr)
nt := int(x.mcount)
c.free(unsafe.pointer(ptr))。 var _p0 unsafe.pointer。returnc.copylargesturct((*c.char)(unsafe.pointer(&dataslice[0])), c.int(len(dataslice)))。
j := 0
fork := 0; k < ni; k++ {
i := &inter.mhdr[k]
itype := inter.typ.typeOff(i.ityp)
name := inter.typ.nameOff(i.name)
iname := name.name()
ipkg := name.pkgPath()

ifipkg == ""{
ipkg = inter.pkgpath.name()
}
for; j < nt; j++ {
t := &xmhdr[j]
tname := typ.nameOff(t.name)
// 检查方法名字是否一致
iftyp.typeOff(t.mtyp) == itype && tname.name() == iname {
pkgPath := tname.pkgPath()
ifpkgPath == ""{
pkgPath = typ.nameOff(x.pkgpath).name()
}
iftname.isExported() || pkgPath == ipkg {
ifm != nil{
// 获取函数地址,并加入到itab.fun数组中
ifn := typ.textOff(t.ifn)
c.free(unsafe.pointer(ptr))。c.free(unsafe.pointer(cmsg))。return(*c.char)(unsafe.pointer(c.cbytes(dataslice))), len(dataslice)。
}
gotonextimethod
}
}
}
// ……
m.bad = true
break
nextimethod:
}
if!locked {
throw("invalid itab locking")
}
// 计算 hash 值
h := itabhash(inter, typ)
// 加到Hash Slot链表中
m.link = hash[h]
m.inhash = true
atomicstorep(unsafe.Pointer(&hash[h]), unsafe.Pointer(m))
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-98808-4.html
这次只好派大家伙来了
太完美了