golang中slice怎么用

小编给大家分享一下golang中slice怎么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

专注于为中小企业提供成都网站设计、做网站、成都外贸网站建设公司服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业化州免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了1000+企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。

slice 结构定义

type slice struct {

    array unsafe.Pointer

    len   int

    cap   int

}

创建slice

// maxSliceCap returns the maximum capacity for a slice.

func maxSliceCap(elemsize uintptr) uintptr {

    if elemsize < uintptr(len(maxElems)) {

        return maxElems[elemsize]

    }

    return _MaxMem / elemsize

}

func makeslice(et *_type, len, cap int) slice {

    // NOTE: The len > maxElements check here is not strictly necessary,

    // but it produces a 'len out of range' error instead of a 'cap out of range' error

    // when someone does make([]T, bignumber). 'cap out of range' is true too,

    // but since the cap is only being supplied implicitly, saying len is clearer.

    // See issue 4085.

    // 计算最大可分配长度

    maxElements := maxSliceCap(et.size)

    if len < 0 || uintptr(len) > maxElements {

        panic(errorString("makeslice: len out of range"))

    }

    if cap < len || uintptr(cap) > maxElements {

        panic(errorString("makeslice: cap out of range"))

    }

    // 分配连续区间

    p := mallocgc(et.size*uintptr(cap), et, true)

    return slice{p, len, cap}

}

slice 扩容

// cap 目标容量

func growslice(et *_type, old slice, cap int) slice {

    if et.size == 0 {

        if cap < old.cap {

            panic(errorString("growslice: cap out of range"))

        }

        // append should not create a slice with nil pointer but non-zero len.

        // We assume that append doesn't need to preserve old.array in this case.

        return slice{unsafe.Pointer(&zerobase), old.len, cap}

    }

    newcap := old.cap

    doublecap := newcap + newcap

    if cap > doublecap {

        newcap = cap

    } else {

        // 小于1024,*2扩容

        if old.len < 1024 {

            newcap = doublecap

        } else {

            // 大于1024,*1.25

            for newcap < cap {

                newcap += newcap / 4

            }

        }

    }

    var lenmem, newlenmem, capmem uintptr

    const ptrSize = unsafe.Sizeof((*byte)(nil))

    switch et.size {

    case 1:

        lenmem = uintptr(old.len)

        newlenmem = uintptr(cap)

        capmem = roundupsize(uintptr(newcap))

        newcap = int(capmem)

    case ptrSize:

        lenmem = uintptr(old.len) * ptrSize

        newlenmem = uintptr(cap) * ptrSize

        capmem = roundupsize(uintptr(newcap) * ptrSize)

        newcap = int(capmem / ptrSize)

    default:

        lenmem = uintptr(old.len) * et.size

        newlenmem = uintptr(cap) * et.size

        capmem = roundupsize(uintptr(newcap) * et.size)

        newcap = int(capmem / et.size)

    }

    if cap < old.cap || uintptr(newcap) > maxSliceCap(et.size) {

        panic(errorString("growslice: cap out of range"))

    }

    var p unsafe.Pointer

    if et.kind&kindNoPointers != 0 {

        p = mallocgc(capmem, nil, false)

        memmove(p, old.array, lenmem)

        // The append() that calls growslice is going to overwrite from old.len to cap (which will be the new length).

        // Only clear the part that will not be overwritten.

        memclrNoHeapPointers(add(p, newlenmem), capmem-newlenmem)

    } else {

        // Note: can't use rawmem (which avoids zeroing of memory), because then GC can scan uninitialized memory.

        p = mallocgc(capmem, et, true)

        if !writeBarrier.enabled {

            memmove(p, old.array, lenmem)

        } else {

            for i := uintptr(0); i < lenmem; i += et.size {

                typedmemmove(et, add(p, i), add(old.array, i))

            }

        }

    }

    // 新slice

    return slice{p, old.len, newcap}

}

以上是“golang中slice怎么用”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注创新互联行业资讯频道!


名称栏目:golang中slice怎么用
网页路径:http://myzitong.com/article/jhcpoc.html