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 · 10959 次点击
    这是一个创建于 1513 天前的主题,其中的信息可能已经有所发展或是发生改变。

    居然还有 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  
       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   ·   实用小工具   ·   1152 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 23:50 · PVG 07:50 · LAX 15:50 · JFK 18:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.