funcTestSliceNew(t *testing.T) { //No.1 s1 := []int{1, 2, 3} fmt.Printf("len is %d, cap is %d , is nil %t\n", len(s1), cap(s1), s1 == nil)
//No.2 s2 := make([]int, 0, 10) fmt.Printf("len is %d, cap is %d , is nil %t\n", len(s2), cap(s2), s2 == nil)
//No.3 var s3 []int fmt.Printf("len is %d, cap is %d , is nil %t\n", len(s3), cap(s3), s3 == nil)
//No.4 // new 函数返回是指针类型,所以需要使用 * 号来解引用 s4 := *new([]int) fmt.Printf("len is %d, cap is %d , is nil %t\n", len(s3), cap(s3), s4 == nil) }
=== RUN TestSliceNew len is 3, cap is 3 , is nilfalse len is 0, cap is 10 , is nilfalse len is 0, cap is 0 , is niltrue len is 0, cap is 0 , is niltrue --- PASS: TestSliceNew (0.00s) PASS
总共常用的是3中方式,其中第三种,第四种就不要用了,这里有2中类型,1个叫”nil切片”,1个叫”empty切片”,官方推荐使用nil切片,也就是var s []int这种方式
The former declares a nil slice value, while the latter is non-nil but zero-length. They are functionally equivalent—their len and cap are both zero—but the nil slice is the preferred style.
funcmallocgc(size uintptr, typ *_type, needzero bool)unsafe.Pointer { if gcphase == _GCmarktermination { throw("mallocgc called with gcphase == _GCmarktermination") }
if size == 0 { return unsafe.Pointer(&zerobase) } //xxxx }
// base address for all 0-byte allocations var zerobase uintptr
funcTestSlice1(t *testing.T) { s := make([]int, 0) fmt.Printf("len is %d, cap is %d ", len(s), cap(s)) hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s)) fmt.Printf("ptr is %x \n", hdr.Data)
s = append(s, 1) fmt.Printf("len is %d, cap is %d ", len(s), cap(s)) hdr = (*reflect.SliceHeader)(unsafe.Pointer(&s)) fmt.Printf("ptr is %x \n", hdr.Data)
s = append(s, 2) fmt.Printf("len is %d, cap is %d ", len(s), cap(s)) hdr = (*reflect.SliceHeader)(unsafe.Pointer(&s)) fmt.Printf("ptr is %x \n", hdr.Data)
s = append(s, 3) fmt.Printf("len is %d, cap is %d ", len(s), cap(s)) hdr = (*reflect.SliceHeader)(unsafe.Pointer(&s)) fmt.Printf("ptr is %x \n", hdr.Data)
s = append(s, 4) fmt.Printf("len is %d, cap is %d ", len(s), cap(s)) hdr = (*reflect.SliceHeader)(unsafe.Pointer(&s)) fmt.Printf("ptr is %x \n", hdr.Data) }
=== RUN TestSlice1 len is 0, cap is 0 ptr is c00006ae58 len is 1, cap is 1 ptr is c0000162c0 len is 2, cap is 2 ptr is c0000162d0 len is 3, cap is 4 ptr is c00001e100 len is 4, cap is 4 ptr is c00001e100 --- PASS: TestSlice1 (0.00s) PASS
In a function call, the function value and arguments are evaluated in the usual order. After they are evaluated, the parameters of the call are passed by value to the function and the called function begins execution. The return parameters of the function are passed by value back to the caller when the function returns.
Map types are reference types, like pointers or slices, and so the value of m above is nil; it doesn't point to an initialized map. A nil map behaves like an empty map when reading, but attempts to write to a nil map will cause a runtime panic; don't do that. To initialize a map, use the built in make function:
funcappendSlice(s []int) { hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s)) fmt.Printf("slice B len is %d, cap is %d , point is %p, 头指针为 %d\n", len(s), cap(s), &s, hdr.Data) s = append(s, 6) }
=== RUN TestSlice2 slice A len is 5, cap is 8 , point is 0xc0000ba030, 头指针为 824634409344 slice B len is 5, cap is 8 , point is 0xc0000ba048, 头指针为 824634409344 输出s的第六位值为 6 --- PASS: TestSlice2 (0.00s) PASS