V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
superhot
V2EX  ›  Go 编程语言

新手提问, Go 作为一个 GC 语言,为什么要设计成带指针类型的呢?

  •  
  •   superhot · 1 天前 · 3127 次点击

    既然无需手动管理内存,像 Java/Python/JS 那样不在语法层面上区分 primitive value 和 reference value 不是更简洁吗?为什么不支持指针运算,却还要有指针类型呢?

    25 条回复    2025-03-22 12:35:22 +08:00
    LitterGopher
        1
    LitterGopher  
       1 天前
    func Inc(a *int) {
    (*a)++
    }


    为了解决类似这样的情况?
    pathletboy
        2
    pathletboy  
       1 天前   ❤️ 4
    有没有可能是为了兼容 cgo ?
    songray
        3
    songray  
       1 天前
    形如 Java/Python/JS 的值类型和引用类型是一种「隐式规则」,所以很难说「隐式规则」和「显示指定」之间的优劣,各有各的问题,比如传递后的对象是否还是原来的引用在有些情况下不明确。
    jiangzm
        4
    jiangzm  
       1 天前
    @LitterGopher #1 这种直接修改值类型参数本身就是设计问题,可以加关键字让编译器去做
    chor02
        5
    chor02  
       1 天前
    为了区分基础类型吧,基础类型都有默认值. 觉得没有做到去掉 nil 是一个遗憾
    ipwx
        6
    ipwx  
       1 天前
    值类型可以是栈对象,比堆对象更高效。

    C# 的 gc 比 Java 看上去牛逼的原因就是因为 C# 从诞生开始就支持值类型。虽然 Java 的 GC 牛逼得多但也是逼出来的。所以保留值类型,可以让 go 程序有可能更高效。

    虽然 go 有指针逃逸分析,和自动优化堆对象,但是众所周知,go 的编译是出了名的快(简陋)

    所以有些 go 的缓存库标榜自己是 pointer-free 的(全都分配在 []value 上),因此性能比别人好。
    strobber16
        7
    strobber16  
       1 天前 via Android
    当然是强制程序员有意识的区分自己是在传值还是传引用。这和 gc 不 gc 的没关系。传值不影响外面,传引用会影响外面。这在并发运算时尤其重要
    minami
        8
    minami  
       1 天前   ❤️ 1
    问就是保留了 C 语言的风味
    shiny
        9
    shiny  
       1 天前
    PHP 都有指针
    InkStone
        10
    InkStone  
       1 天前
    @strobber16 C++里同时有引用和指针,在这件事上引用语义才是更直观的。为什么会选用指针而非引用的方式来区分这二者,其实还挺奇怪的
    whyso
        11
    whyso  
       1 天前
    指针类型× 引用类型√
    wei2629
        12
    wei2629  
       1 天前
    为了区分拷贝 和引用吧。
    bruce0
        13
    bruce0  
       1 天前
    我猜测 go 是想成为简单的 C(自动管理内存的 C), 所以保留了 C 中的一些概念. 但是 go 也有想 Java 一样,默认传引用的类型, map, chan. 反而我觉得 Java 这种 class 默认传引用 `还不好`,不够灵活.
    MoYi123
        14
    MoYi123  
       1 天前
    因为指针可以是 null, 但是引用或者值不能是空.
    估计是不想搞 optional, 就直接用指针了.
    ccpp132
        15
    ccpp132  
       1 天前
    不能做运算的指针,其实就是别的语言的引用。只有叫法或者语法上的一点差异了
    InkStone
        16
    InkStone  
       1 天前
    @MoYi123 确实。optional 对类型系统和后端优化的要求更高一些,Go 初版连泛型都没有,不太能做 nullable reference ,也只能上指针了。
    strobber16
        17
    strobber16  
       1 天前
    另外也并不是真的不能运算的指针啊,不是给你留了 unsafe.Pointer 这个口子吗
    lloovve
        18
    lloovve  
       1 天前 via iPhone
    对于用习惯 c ,迁移代码,太喜欢这点了
    voidmnwzp
        19
    voidmnwzp  
       1 天前
    不能运算? ptr:=(uintptr)((unsafe.Pointer)(&x));ptr=ptr+unsafe.Sizeof(x)
    minottomie4383
        20
    minottomie4383  
       1 天前
    我没记错的话,go 有 unsafe 是可以读内存字节的
    CapNemo
        21
    CapNemo  
       1 天前
    如果指 1 楼的情况,那就是一个引用传值,避免反复拷贝一些比较大的 struct 等。如果指 unsafe 里的指针,这个主要是为了方便搞一些强制类型转换和链接 c 语言库。
    gam2046
        22
    gam2046  
       1 天前
    我认为极大程度上是为了 CGO 保留的指针。如果说没有 CGO ,指针的意义就少了一半。
    leonshaw
        23
    leonshaw  
       1 天前 via Android
    Java, python 这种,primitive 类型以外的变量都是引用。go 的变量都是值,所以需要通过指针引入 indirection 。不然同时有值类型和引用类型会让语法更晦涩,参考 C++。
    yianing
        24
    yianing  
       12 小时 33 分钟前
    golang 除了 map ,slice ,chan 这些内置的,没有引用类型,都是值类型
    zzhirong
        25
    zzhirong  
       10 小时 3 分钟前
    除了以上其他人所说,我认为还有一个重要原因,在 Go 中,对象的概念主要通过 struct 实现,而 struct 为值类型,为了让方法修改其内容,只能依靠指针,所以,只要还有值类型存在,而函数传参均为值传递,那么如果希望定义能够修改对象本身的方法,就必须使用指针。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2743 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 14:38 · PVG 22:38 · LAX 07:38 · JFK 10:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.