设为首页 加入收藏

TOP

说说不知道的Golang中参数传递(三)
2019-01-16 12:08:36 】 浏览:384
Tags:说说 知道 Golang 参数 传递
为此,我们需要关注的是fmt包中fmtPointer():

func (p *pp) fmtPointer(value reflect.Value, verb rune) {
    var u uintptr
    switch value.Kind() {
    case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
        u = value.Pointer()
    default:
        p.badVerb(verb)
        return
    }
    ...
}

我们发现在fmtPointer()中,对于map、channel和slice,都被当成了指针来处理,通过Pointer()函数获取对应的值的指针。我们知道channel和map是因为make函数返回的就已经是指针了,无可厚非,但是对于slice这个非指针,在value.Pointer()是如何处理的呢?

// If v's Kind is Slice, the returned pointer is to the first
// element of the slice. If the slice is nil the returned value
// is 0.  If the slice is empty but non-nil the return value is non-zero.
func (v Value) Pointer() uintptr {
    // TODO: deprecate
    k := v.kind()
    switch k {
    case Chan, Map, Ptr, UnsafePointer:
        return uintptr(v.pointer())
    case Func:
        ...
    case Slice:
        return (*SliceHeader)(v.ptr).Data
    }
    ...
}

果不其然,在Pointer()函数中,对于Slice类型的数据,返回的一直是指向第一个元素的地址,所以我们通过fmt.Printf()中%p来打印Slice的地址,其实打印的结果是内部存储数组元素的首地址,这也就解释了问题2中为什么地址会一致的原因了。

总结

通过上述的一系列总结,我们可以很高兴的确定的是:在golang中的传参一定是值传递了!

然而golang隐藏了一些实现细节,在处理map,channel和slice等这些内置结构的数据时,其实处理的是一个指针类型的数据,也是因此,在函数内部可以修改(部分修改)数据的内容。

但是,这些修改得以实现的原因,是因为数据本身是个指针类型,而不是因为golang采用了引用传递,注意二者的区别哦~

此文已由作者授权腾讯云+社区在各渠道发布

获取更多新鲜技术干货,可以关注我们腾讯云技术社区-云加社区官方号及知乎机构号

首页 上一页 1 2 3 下一页 尾页 3/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Golang并行判断素数 下一篇[日常] Go-逐行读取文本信息

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目