5. chan
var var_chan = make(chan int ,1)
func func1(){
...
var var2_chan = make(chan int ,3)
...
}
1、通过runtime.makechan()创建channel。
2、第一个参数为chan类型信息
3、返回值类型为*hchan
即: chan变量实际为一个hchan指针
由全局变量也可以看出。
func makechan(t *chantype, size int) *hchan {
...
var c *hchan
...
return c
}
"".var_chan SBSS size=8
0x014f 00335 (type.go:48) LEAQ type.chan int(SB), AX
0x0156 00342 (type.go:48) PCDATA $2, $0
0x0156 00342 (type.go:48) MOVQ AX, (SP)
0x015a 00346 (type.go:48) MOVQ $3, 8(SP)
0x0163 00355 (type.go:48) CALL runtime.makechan(SB)
0x0168 00360 (type.go:48) PCDATA $2, $1
0x0168 00360 (type.go:48) MOVQ 16(SP), AX //返回值为 *hchan 类型
0x016d 00365 (type.go:48) PCDATA $2, $0
0x016d 00365 (type.go:48) PCDATA $0, $5
0x016d 00365 (type.go:48) MOVQ AX, "".var2_chan+144(SP)
chan类型信息
type chantype struct { //64 字节
typ _type //48 字节
elem *_type //8 字节
dir uintptr //8 字节
}
类型信息对应汇编
type..namedata.*chan int- SRODATA dupok size=12
0x0000 00 00 09 2a 63 68 61 6e 20 69 6e 74 ...*chan int
type.*chan int SRODATA dupok size=56
0x0000 08 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 ................
0x0010 ed 7b ed 3b 00 08 08 36 00 00 00 00 00 00 00 00 .{.;...6........
0x0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0030 00 00 00 00 00 00 00 00 ........
rel 24+8 t=1 runtime.algarray+80
rel 32+8 t=1 runtime.gcbits.01+0
rel 40+4 t=5 type..namedata.*chan int-+0
rel 48+8 t=1 type.chan int+0
type.chan int SRODATA dupok size=64
0x0000 08 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 ................
0x0010 91 55 cb 71 02 08 08 32 00 00 00 00 00 00 00 00 .U.q...2........
0x0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0030 00 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00 ................
rel 24+8 t=1 runtime.algarray+80
rel 32+8 t=1 runtime.gcbits.01+0
rel 40+4 t=5 type..namedata.*chan int-+0
rel 44+4 t=6 type.*chan int+0
rel 48+8 t=1 type.int+0
5.1 通过runtime.makechan
src\runtime\chan.go
func makechan(t *chantype, size int) *hchan {
elem := t.elem
// compiler checks this but be safe.
if elem.size >= 1<<16 {
throw("makechan: invalid channel element type")
}
if hchanSize%maxAlign != 0 || elem.align > maxAlign {
throw("makechan: bad alignment")
}
mem, overflow := math.MulUintptr(elem.size, uintptr(size))
if overflow || mem > maxAlloc-hchanSize || size < 0 {
panic(plainError("makechan: size out of range"))
}
// Hchan does not contain pointers interesting for GC when elements stored in buf do not contain pointers.
// buf points into the same allocation, elemtype is persistent.
// SudoG's are referenced from their owning thread so they can't be collected.
// TODO(dvyukov,rlh): Rethink when collector can move allocated objects.
var c *hchan
switch {
case mem == 0:
// Queue or element size is zero.
c = (*hchan)(mallocgc(hchanSize, nil, true))
// Race detector uses this location for synchronization.
c.buf = c.raceaddr()
case elem.kind&kindNoPointers != 0:
// Elements do not contain pointers.
// Allocate hchan and buf in one call.
c = (*hchan)(mallocgc(hchanSize+mem, nil, true))
c.buf = add(unsafe.Pointer(c), hchanSize)
default:
// Elements contain pointers.
c = new(hchan)
c.buf = mallocgc(mem, elem, true)
}
c.elemsize = uint16(elem.size)
c.elemtype = elem
c.dataqsiz = uint(size)
if debugChan {
print("makechan: chan=", c, "; elemsize=", elem.size, "; elemalg=", elem.alg, "; dataqsiz=", size, "\n")
}
return c
}