新手提问, Go 作为一个 GC 语言,为什么要设计成带指针类型的呢? - V2EX
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 208 天前 4764 次点击
    这是一个创建于 208 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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


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

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

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

    所以有些 go 的缓存库标榜自己是 pointer-free 的(全都分配在 []value 上),因此性能比别人好。
    strobber16
        7
    strobber16  
       208 天前 via Android
    当然是强制程序员有意识的区分自己是在传值还是传引用。这和 gc 不 gc 的没关系。传值不影响外面,传引用会影响外面。这在并发运算时尤其重要
    minami
        8
    minami  
       208 天前   2
    问就是保留了 C 语言的风味
    shiny
        9
    shiny  
       208 天前
    PHP 都有指针
    InkStone
        10
    InkStone  
       208 天前
    @strobber16 C++里同时有引用和指针,在这件事上引用语义才是更直观的。为什么会选用指针而非引用的方式来区分这二者,其实还挺奇怪的
    whyso
        11
    whyso  
       208 天前
    指针类型× 引用类型√
    wei2629
        12
    wei2629  
       208 天前
    为了区分拷贝 和引用吧。
    bruce0
        13
    bruce0  
       208 天前
    我猜测 go 是想成为简单的 C(自动管理内存的 C), 所以保留了 C 中的一些概念. 但是 go 也有想 Java 一样,默认传引用的类型, map, chan. 反而我觉得 Java 这种 class 默认传引用 `还不好`,不够灵活.
    MoYi123
        14
    MoYi123  
       208 天前
    因为指针可以是 null, 但是引用或者值不能是空.
    估计是不想搞 optional, 就直接用指针了.
    ccpp132
        15
    ccpp132  
       208 天前
    不能做运算的指针,其实就是别的语言的引用。只有叫法或者语法上的一点差异了
    InkStone
        16
    InkStone  
       208 天前
    @MoYi123 确实。optional 对类型系统和后端优化的要求更高一些,Go 初版连泛型都没有,不太能做 nullable reference ,也只能上指针了。
    strobber16
        17
    strobber16  
       208 天前
    另外也并不是真的不能运算的指针啊,不是给你留了 unsafe.Pointer 这个口子吗
    lloovve
        18
    lloovve  
       208 天前 via iPhone
    对于用习惯 c ,迁移代码,太喜欢这点了
    voidmnwzp
        19
    voidmnwzp  
       208 天前
    不能运算? ptr:=(uintptr)((unsafe.Pointer)(&x));ptr=ptr+unsafe.Sizeof(x)
    minottomie4383
        20
    minottomie4383  
       208 天前
    我没记错的话,go 有 unsafe 是可以读内存字节的
    CapNemo
        21
    CapNemo  
       208 天前
    如果指 1 楼的情况,那就是一个引用传值,避免反复拷贝一些比较大的 struct 等。如果指 unsafe 里的指针,这个主要是为了方便搞一些强制类型转换和链接 c 语言库。
    gam2046
        22
    gam2046  
       208 天前
    我认为极大程度上是为了 CGO 保留的指针。如果说没有 CGO ,指针的意义就少了一半。
    leonshaw
        23
    leonshaw  
       208 天前 via Android
    Java, python 这种,primitive 类型以外的变量都是引用。go 的变量都是值,所以需要通过指针引入 indirection 。不然同时有值类型和引用类型会让语法更晦涩,参考 C++。
    yianing
        24
    yianing  
       207 天前
    golang 除了 map ,slice ,chan 这些内置的,没有引用类型,都是值类型
    zzhirong
        25
    zzhirong  
       207 天前
    除了以上其他人所说,我认为还有一个重要原因,在 Go 中,对象的概念主要通过 struct 实现,而 struct 为值类型,为了让方法修改其内容,只能依靠指针,所以,只要还有值类型存在,而函数传参均为值传递,那么如果希望定义能够修改对象本身的方法,就必须使用指针。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3167 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 00:33 PVG 08:33 LAX 17:33 JFK 20:33
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86