请检查以下代码段:
package main
import (
"fmt"
"time"
)
type field struct {
name string
}
func (p *field) print() {
fmt.Println(p.name)
}
func main() {
fmt.Println("use values:")
// use values in range loop and go rountines
values := []field{{"one"},{"two"},{"three"}}
for _, v := range values {
go v.print()
}
time.Sleep(time.Second)
fmt.Println()
fmt.Println("use pointers:")
// use pointers in range loop and go rountines
poniters := []*field{{"one"},{"two"},{"three"}}
for _, v := range poniters {
go v.print()
}
time.Sleep(time.Second)
}
链接到这里:https :
//play.golang.org/p/cdryPmyWt5
上面的代码将检查for循环中的指针和值之间的差异,而go语句也同时使用。对于代码:
values := []field{{"one"},{"two"},{"three"}}
for _, v := range values {
go v.print()
}
我们知道,控制台将打印 三三三 的结果,因为循环运行到其最终的够程开始执行,其中写V作为片的最后一个元素之前。但是指针呢?
poniters := []*field{{"one"},{"two"},{"three"}}
for _, v := range poniters {
go v.print()
}
好像打印 一二三 ,为什么呢?
谢谢。
答:在调用函数之前先评估参数。在对它们进行评估之后,调用的参数将按值传递给函数,并且被调用函数开始执行,因此:
第一go v.print()
是语法糖go (*field).print(&v)
和
所述第二go v.print()
是语法糖go (*field).print(v)
。
如果for
在goroutines启动之前第一个循环完成,&v
则调用相同,这三个调用都相同。通过time.Sleep(100)
在go v.print()
第一个循环之后添加,请参见代码2 。或go func(v field) { v.print() }(v)
在The Go
Playground(带有的代码3 sync.WaitGroup
)上使用
。
另外,您在这里有 数据竞赛 (请参阅B)。
而对于第二个go (*field).print(v)
位置v
是之前调用参数评估真实指针和三个够程print
,并 有三种不同的地址 。
1-在The Go Playground上尝试:
package main
import (
"fmt"
"time"
)
type field struct {
name string
}
func (p *field) print() {
fmt.Println(p.name)
}
func main() {
fmt.Println("use values:")
// use values in range loop and go rountines
values := []field{{"one"}, {"two"}, {"three"}}
for _, v := range values {
fmt.Println(&v)
go (*field).print(&v) //go v.print()
}
time.Sleep(time.Second)
fmt.Println()
fmt.Println("use pointers:")
// use pointers in range loop and go rountines
poniters := []*field{{"one"}, {"two"}, {"three"}}
for _, v := range poniters {
fmt.Println(v)
go (*field).print(v) //go v.print()
}
time.Sleep(time.Second)
}
输出:
use values:
&{one}
&{two}
&{three}
three
three
three
use pointers:
&{one}
&{two}
&{three}
two
one
three
2-在Go Playground上尝试:
package main
import (
"fmt"
"time"
)
type field struct {
name string
}
func (p *field) print() {
fmt.Println(p.name)
}
func main() {
fmt.Println("use values:")
// use values in range loop and go rountines
values := []field{{"one"}, {"two"}, {"three"}}
for _, v := range values {
fmt.Println(&v)
go v.print() //go (*field).print(&v) //
time.Sleep(100)
}
time.Sleep(time.Second)
fmt.Println()
fmt.Println("use pointers:")
// use pointers in range loop and go rountines
poniters := []*field{{"one"}, {"two"}, {"three"}}
for _, v := range poniters {
fmt.Println(v)
go v.print() //go (*field).print(v) //
}
time.Sleep(time.Second)
}
输出:
use values:
&{one}
one
&{two}
two
&{three}
three
use pointers:
&{one}
&{two}
&{three}
one
two
three
B:您之间存在数据争夺,请尝试go build -race
您的代码,然后运行生成的文件WARNING: DATA RACE
:
输出:
use values:
==================
WARNING: DATA RACE
Read at 0x00c042030210 by goroutine 6:
runtime.convT2E()
Go/src/runtime/iface.go:155 +0x0
main.(*field).print()
.../m.go:14 +0x6c
Previous write at 0x00c042030210 by main goroutine:
main.main()
.../m.go:22 +0x1c3
Goroutine 6 (running) created at:
main.main()
.../m.go:23 +0x204
==================
two
three
three
use pointers:
one
two
three
Found 1 data race(s)
问题内容: 在指令内部创建 隔离作用域 使我们可以将 外部作用域 映射到 内部作用域 。我们已经看到了六种映射到属性的不同方法: = attr &attr @attr = 和 @ 这些作用域映射选项分别做什么? 问题答案: 这可能会造成混淆,但是希望有一个简单的示例可以阐明这一点。首先,让我们将模型绑定与行为分开。 这是一个小提琴,应该有助于将它们联系在一起:http : //jsfiddle.n
我想查询日期范围内的elasticsearch文档。我现在有两个选择,都很适合我。我已经测试了他们两个。1.范围查询2。距离滤波器 因为我现在有一个小数据集,所以无法测试它们的性能。这两者有什么区别?哪一种方法可以更快地检索文档和响应?
问题内容: 我想有一个通用的方法,无论它是作为指针,切片还是数组提供的,都将始终返回结构值。 我对此的处理方式如下: 去游乐场 如您所见,问题出在从a 或。中获取结构。 我如何扩展上面的函数以从数组或切片中获取struct的值? 更新:我要做的就是将变成。 问题答案: 如果你只是想要的类型,即使片是零,你可以使用像这样: 关于,来自http://golang.org/pkg/reflect/#Ty
我使用的是mongoDB PHP,当我使用find查询或聚合框架时,结果是一个游标,我可以使用foreach循环或while循环对游标进行迭代。例如,我要执行以下查询 我可以使用以下两种方法迭代结果
给定max number和range number,我希望打印出以下内容,但尽可能简短。我不知道这是否可以通过IntStream实现。 输入:max=36(或任意数)范围=10(或任意数) 输出:0-910-1920-2930-35 我的代码:
问题内容: 在下一个稳定的AngularJS发行时,我将应用程序从 1.0.8 迁移到 1.2 。 在AngularJS 1.0.8中 ,可以为诸如的指令设置隔离范围。然后,该指令将使用其自己的功能而不是控制器的功能。 Java脚本 在AngularJS 1.2中, 此行为不再起作用。单击该按钮将立即激活控制器的功能。 参见以下jsFiddle比较: 角1.0.8 角1.2.0 到底发生了什么变化