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

go 语言就很离谱

  •  
  •   leeraya 2020-10-29 11:42:08 +08:00 11520 次点击
    这是一个创建于 1888 天前的主题,其中的信息可能已经有所发展或是发生改变。

    居然还有 func type 这种东西。今天遇到要循环生成 type func 的对象: type FieldResolveFn func(p ResolveParams) (interface{}, error)

    结果循环生成的 func 都是一样的,最后都变成可最后生成的那一个。 该怎么解决啊,老哥们

    64 条回复    2020-11-30 12:45:23 +08:00
    THESDZ
        1
    THESDZ  
       2020-10-29 11:45:03 +08:00
    是不是指针的问题,导致被最后一个覆盖了
    Glauben
        2
    Glauben  
       2020-10-29 11:47:52 +08:00
    你是怎么生成的,上代码
    cmdOptionKana
        3
    cmdOptionKana  
       2020-10-29 11:48:59 +08:00   4
    为什么要这样问问题…… 标题引战,正文又不上代码。
    geebos
        4
    geebos  
    PRO
       2020-10-29 11:50:24 +08:00
    你要保存函数指针啊
    hakono
        5
    hakono  
       2020-10-29 11:50:37 +08:00
    感觉 lz 这样搞,很可能是自己的问题。。。。
    guader
        6
    guader  
       2020-10-29 11:51:18 +08:00   12
    鱼 好大的鱼 虎纹鲨鱼
    keepeye
        7
    keepeye  
       2020-10-29 11:57:43 +08:00
    若不是你自己的问题,我吃屎
    baiyi
        8
    baiyi  
       2020-10-29 11:58:10 +08:00
    应该是 go 的经典问题,循环的时候传指针了
    leeraya
        9
    leeraya  
    OP
       2020-10-29 12:01:23 +08:00
    例如:
    type Greeting func(name string) string
    func main() {

    test := make([]Greeting, 3)

    nameArr := []string{"lee", "ray", "Pool"}

    for index, name1 := range nameArr {
    // if index == 0 {
    // test[index] = func(name string) string {
    // fmt.Println("hello " + name + name1 + strconv.Itoa(index))
    // return "hello " + name + name1 + strconv.Itoa(index)
    // }
    // } else {
    // test[index] = func(name string) string {
    // fmt.Println("hello " + name + name1 + strconv.Itoa(index))
    // return "hello " + name + name1 + strconv.Itoa(index)
    // }
    // }
    test[index] = func(name string) string {
    fmt.Println("hello " + name + name1 + strconv.Itoa(index))
    return "hello " + name + name1 + strconv.Itoa(index)
    }

    }
    }
    debug 看 test 数组,元素都是一样的
    FlyingDough
        10
    FlyingDough  
       2020-10-29 12:04:36 +08:00
    怪 Go?
    rrfeng
        11
    rrfeng  
       2020-10-29 12:09:22 +08:00
    不怪 Go
    coderxy
        12
    coderxy  
       2020-10-29 12:10:18 +08:00
    你这是循环的时候错误的使用了指针吧
    lcdtyph
        13
    lcdtyph  
       2020-10-29 12:15:37 +08:00 via iPhone
    for index, name1 := range xxx {
    index, name1 := index, name1
    // the rest code...
    }
    hakono
        14
    hakono  
       2020-10-29 12:19:20 +08:00   1
    看了 LZ 的代码原来是这么回事,问题不在闭包,而是 for index, name1 := range nameArr{} 中, 每次循环都是在重复利用 name1 为 name1 赋不同的值 ,name1 本身的值在不停变换
    闭包中引用同一个变量的话,那必定是闭包的里变量的值都一样的

    https://studygolang.com/articles/14696

    ```

    for index := range nameArr {
    tmpName := nameArr[index]
    test[index] = func(name string) string {
    fmt.Println("hello " + name + tmpName + strconv.Itoa(index))
    return "hello " + name + tmpName + strconv.Itoa(index)
    }

    }
    ```
    改成这样就行了
    hakono
        15
    hakono  
       2020-10-29 12:22:23 +08:00   5
    都忘了 V2EX 不能回复 Markdown 了
    例子: https://play.golang.org/p/4qyRFCv2AMF

    关于 for range 这个, 我一般是不太喜欢使用 for idx, value := slice1 的写法的, 因为 value 是指的拷贝,每次循环都要拷贝一遍,大量循环的时候性能会有影响,所以默认都是 for idx := slice1 这样
    wangyzj
        16
    wangyzj  
       2020-10-29 12:27:06 +08:00 via iPhone
    函数指针
    BoarBoar
        17
    BoarBoar  
       2020-10-29 12:50:10 +08:00
    这不都是很基础的东西吗,传值还是传指针,深拷贝浅拷贝我记得是大一学的
    函数作为一等公民也是 js 等脚本语言广泛使用的
    所以我一直觉得与其学多少新东西,先打好基础才是最重要的,很多东西大同小异,万变不离其宗
    zunceng
        18
    zunceng  
       2020-10-29 13:30:51 +08:00   2
    leeraya
        19
    leeraya  
    OP
       2020-10-29 13:42:02 +08:00
    @hakono 太牛了,感谢大佬。
    wander639
        20
    wander639  
       2020-10-29 13:44:37 +08:00
    可以新开一贴:用 go 语言的人就很离谱
    lookbackagain
        21
    lookbackagain  
       2020-10-29 13:58:31 +08:00
    这么基础的问题,怪 go 语言就离谱
    yufpga
        22
    yufpga  
       2020-10-29 14:00:09 +08:00   1
    // 自己细品
    for index, name1 := range nameArr {
    test[index] = func(i int, name1 string) Greeting {
    return func(name string) string {
    fmt.Println("hello " + name + name1 + strconv.Itoa(i))
    return "hello " + name + name1 + strconv.Itoa(i)
    }
    }(index, name1)
    }
    KaynW
        23
    KaynW  
       2020-10-29 14:06:25 +08:00
    ??? 这问题还能怪 Go 啊?
    gowk
        24
    gowk  
       2020-10-29 14:06:46 +08:00 via Android   2
    滚!
    gowk
        25
    gowk  
       2020-10-29 14:10:47 +08:00   1
    忘加狗头了
    mrgeneral
        26
    mrgeneral  
       2020-10-29 14:18:41 +08:00
    一个帖子多重反转。
    看标题我就知道要引战了。
    看内容没想到连代码都没贴就开始提问题了,得学习下「如何提问」
    看了贴出来的代码,没想到是一个很基础的问题,得学习下「 The Go Programming Language 」。

    但凡认真学习下也不会踩这个坑: https://book.douban.com/subject/27044219/ 书里说的很明白。

    最后,其实是楼主标题党了。
    realbender
        27
    realbender  
       2020-10-29 14:23:11 +08:00
    去面试这样子笔试都过不了的
    yaphets666
        28
    yaphets666  
       2020-10-29 14:26:55 +08:00
    Javascript 这有类似的问题
    JerryChan31
        29
    JerryChan31  
       2020-10-29 14:28:05 +08:00   2
    这贴是对 Cunningham's Law 的伟大实践(手动狗头
    vZexc0m
        30
    vZexc0m  
       2020-10-29 15:07:52 +08:00
    @hakono #14 但是为什么 test 内部三个函数的地址却还是一样的呢
    ghjacky
        31
    ghjacky  
       2020-10-29 15:10:38 +08:00
    你这不是 go 的问题吧,这是对编程里边的 for 循环有异议?
    GopherDaily
        32
    GopherDaily  
       2020-10-29 15:14:28 +08:00
    怪我,不用说了
    chengyunbo
        33
    chengyunbo  
       2020-10-29 15:16:46 +08:00
    新手上路基本都会碰到这个坑,特别是从 PHP 转过来的,趟坑多了,慢慢体会,我已经趟了一路了。
    zu1k
        34
    zu1k  
       2020-10-29 15:26:13 +08:00 via Android
    看了一遍,又浪费时间了
    hakono
        35
    hakono  
       2020-10-29 16:22:22 +08:00
    @vZexc0m 涉及到底层所以不是非常了解,但从理解上来说,闭包调用的时候函数定义和环境是分开的,所以环境虽然不同,但是指向的都是同一个地址
    yuhaoyuhao
        36
    yuhaoyuhao  
       2020-10-29 16:44:16 +08:00
    @vZexc0m 我觉得应该算是一种编译器优化。
    index90
        37
    index90  
       2020-10-29 16:46:16 +08:00
    @vZexc0m 函数地址肯定都是一样的呀,了解一下 linux 进程内存模型,函数都在代码段里。

    编码时候看起来是函数是个变量,实际上只有一个函数的代码段,函数内的变量实际上是参数。
    wellsc
        38
    wellsc  
       2020-10-29 16:50:43 +08:00
    这个坑就离谱
    victor
        39
    victor  
       2020-10-29 16:57:09 +08:00
    基础差不要紧,请用 https://github.com/kyoh86/scopelint 检查 range 的写法。
    kkbblzq
        40
    kkbblzq  
       2020-10-29 16:57:40 +08:00
    这个贴就很离谱
    misaka19000
        41
    misaka19000  
       2020-10-29 17:03:55 +08:00
    V 站的提问质量每况愈下
    Zhangxiaopa
        42
    Zhangxiaopa  
       2020-10-29 17:14:33 +08:00
    @mrgeneral 但是楼主成功了
    sulinehk
        43
    sulinehk  
       2020-10-29 18:01:10 +08:00   1
    这个坑还常见的,以前写过一篇博客: https://www.sulinehk.com/post/golang-closure-details/
    bigNewsMaker
        44
    bigNewsMaker  
       2020-10-29 18:50:45 +08:00 via iPhone
    不要老是想着搞一个大新闻~
    yulon
        45
    yulon  
       2020-10-29 19:04:52 +08:00   2
    天天 Go 语言离谱,JS 离谱的,来写 C++ 嘛,求求你们来写 C++ 嘛,赚得还更多,为啥不来写捏
    xuanbg
        46
    xuanbg  
       2020-10-29 19:08:36 +08:00
    这不是和在一个循环里面把一个对象属性改改放进去 list,然后发现整个 list 里面的对象属性全都和最后一个一样一回事嘛。
    xuanbg
        47
    xuanbg  
       2020-10-29 19:09:55 +08:00
    @yulon C 艹在他们手里就更离谱了
    shm7
        48
    shm7  
       2020-10-29 19:49:26 +08:00 via iPhone
    函数返回有类型很奇怪吗?
    -
    PHP 就很离谱
    Python 就很离谱
    JS 就很离谱
    Lua 就很离谱
    Lisp 就很离谱
    C 就很离谱
    C++就很离谱
    Java 就很离谱
    GO 就很离谱

    -
    计算机就是离谱
    人类就是离谱
    地球就是离谱
    银河系就是离谱
    宇宙就是离谱
    大爆炸就是离谱
    coderunI
        49
    coderunI  
       2020-10-29 21:58:31 +08:00
    这不就是 js 经典闭包问题吗?
    cmdOptionKana
        50
    cmdOptionKana  
       2020-10-29 22:14:51 +08:00
    @sulinehk 博客样式很好看
    MemoryCorner
        51
    MemoryCorner  
       2020-10-29 23:30:15 +08:00
    楼主就很离谱
    eudore
        52
    eudore  
       2020-10-30 08:41:04 +08:00
    楼主就很离谱
    mscb
        53
    mscb  
       2020-10-30 08:50:35 +08:00 via Android
    一定要先学好基础
    wangritian
        54
    wangritian  
       2020-10-30 09:15:41 +08:00
    很遗憾看不到 7 楼吃屎
    Hider5
        55
    Hider5  
       2020-10-30 09:20:35 +08:00
    楼主就很离谱
    deplives
        56
    deplives  
       2020-10-30 09:35:00 +08:00
    楼主就很离谱
    OMGZui
        57
    OMGZui  
       2020-10-30 10:36:31 +08:00
    楼主就很离谱
    shineqaq
        58
    shineqaq  
       2020-10-30 10:55:21 +08:00
    楼主就很离谱
    jewer3330
        59
    jewer3330  
       2020-10-30 11:13:34 +08:00
    楼主就很离谱
    JB18CM
        60
    JB18CM  
       2020-10-30 11:29:36 +08:00
    楼主就很离谱
    wangritian
        61
    wangritian  
       2020-10-30 17:25:08 +08:00
    楼主就很离谱
    xiatian0415
        62
    xiatian0415  
       2020-10-30 20:08:34 +08:00
    你们不对劲
    DonkeyBenjamin
        63
    DonkeyBenjamin  
       2020-10-31 04:37:37 +08:00
    任何函数是 first-class, closure 是 deep binding 的都有这种现象,不是 go 特有的
    这楼主不懂乱喷
    sunshinev
        64
    sunshinev  
       2020-11-30 12:45:23 +08:00
    指针 指针 !!!!引用!!!引用
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     943 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 22:35 PVG 06:35 LAX 14:35 JFK 17:35
    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