golang for,range的坑

yhao917 · · 5138 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

for,range 的k,v变量在整个遍历过程中共用,不能直接进行引用传递,即地址传递,但循环内定义的变量只能为当前循环所使用。

错误代码:

package main

import (
    "encoding/json"
    "log"
    "time"
)

type test struct {
    Name string `bson:"name" json:"name" yaml:"name"` // Command name (unique on the profile)
}

func (test test) String() string {
    out, err := json.Marshal(test)
    if err != nil {
        return err.Error()
    }
    return string(out)
}

func main() {
    var a, b, c test
    a.Name = "a"
    b.Name = "b"
    c.Name = "c"
    src := []test{a, b, c}
    log.Println(src)
    var dec []*test
    for _, v := range src {
        log.Println(v)
        dec = append(dec, &v)
    }
    time.Sleep(1 * time.Second)
    log.Println(dec)
}

输出结果:


2019/03/20 13:28:34 [{"name":"a"} {"name":"b"} {"name":"c"}]
2019/03/20 13:28:34 {"name":"a"}
2019/03/20 13:28:34 {"name":"b"}
2019/03/20 13:28:34 {"name":"c"}
2019/03/20 13:28:35 [{"name":"c"} {"name":"c"} {"name":"c"}]

示例代码对test结构体定义了String方法,会打印地址指向的具体内容,详情见我另外一篇文章:利用fmt.Stringer 接口实现自定义日志打印

示例代码输出dec结果所有成员皆为遍历的最后一个地址,非预期值,正确使用应如下:

package main

import (
    "encoding/json"
    "log"
    "time"
)

type test struct {
    Name string `bson:"name" json:"name" yaml:"name"` // Command name (unique on the profile)
}

func (test test) String() string {
    out, err := json.Marshal(test)
    if err != nil {
        return err.Error()
    }
    return string(out)
}

func main() {
    var a, b, c test
    a.Name = "a"
    b.Name = "b"
    c.Name = "c"
    src := []test{a, b, c}
    log.Println(src)
    var dec []*test
    for _, v := range src {
        value := v
        dec = append(dec, &value)
    }
    time.Sleep(1 * time.Second)
    log.Println(dec)
}

输出结果:

2019/03/20 13:36:41 [{"name":"a"} {"name":"b"} {"name":"c"}]
2019/03/20 13:36:42 [{"name":"a"} {"name":"b"} {"name":"c"}]

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:yhao917

查看原文:golang for,range的坑

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:701969077

5138 次点击  
加入收藏 微博
1 回复  |  直到 2019-03-20 19:02:57
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传