温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

golang中slice怎么用

发布时间:2021-12-15 11:23:31 来源:亿速云 阅读:162 作者:小新 栏目:大数据

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

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怎么用”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI