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"}]