我编写了一个简单的小例子,将1000万条记录插入mongodb.我开始按顺序工作.然后我查找了如何进行并发,并找到了goroutines.这看起来像我想要的,但它并不像我期望的那样表现.我实现了一个WaitGroup来阻止程序在所有goroutine完成之前退出,但我仍然遇到问题.
所以我将从正在发生的事情开始然后显示代码.当我运行没有goroutine的代码时,所有1000万条记录都插入mongodb罚款.然而,当我添加goroutine时,一些不确定的数量被输入..一般在8500左右给予或采取几百.我检查了mongodb日志,看它是否有问题,没有任何显示.所以我不确定是什么,可能是,只是没有被记录.无论如何,这是代码:
(旁注:我一次只做1条记录,但我把它拆分成一种方法,所以我可以在将来一次测试多条记录......只是还没弄明白如何用mongodb做到这一点然而.)
package main
import (
"fmt"
"labix.org/v2/mgo"
"strconv"
"time"
"sync"
)
// structs
type Reading struct {
Id string
Name string
}
var waitGroup sync.WaitGroup
// methods
func main() {
// Setup timer
startTime := time.Now()
// Setup collection
collection := getCollection("test", "readings")
fmt.Println("collection complete: " + strconv.FormatFloat(time.Since(startTime).Seconds(), 'f', 2, 64))
// Setup readings
readings := prepareReadings()
fmt.Println("readings prepared: " + strconv.FormatFloat(time.Since(startTime).Seconds(), 'f', 2, 64))
// Insert readings
for i := 1; i <= 1000000; i++ {
waitGroup.Add(1) …Run Code Online (Sandbox Code Playgroud) 在Go中,如果我尝试从通道接收,程序的执行将被停止,直到某个值在通道中.但是,我想要做的是让程序继续执行,如果通道中有值,则对其执行操作.
我想到的伪代码是这样的:
mychan := make(chan int, 1)
go someGoRoutine(mychan) // This might put some value in mychan at some point
for {
if something in "mychan" {
// Remove the element from "mychan" and process it
} else {
// Other code
}
}
Run Code Online (Sandbox Code Playgroud)
据我所知,我不能简单地使用,v <- mychan因为这将阻止程序执行,直到值可用.在Go中这样做的方法是什么?
package main
import (
"fmt"
"time"
)
func main() {
c := make(chan struct{})
count := 1
go func() {
for {
fmt.Println("foo", count)
count++
time.Sleep(2)
}
c <- struct{}{}
}()
fmt.Println("Hello World!")
<-c
}
Run Code Online (Sandbox Code Playgroud)
这是我的代码,我发现它没有在每个循环中睡2,并且很快打印出来.这是什么原因?我搜索的是睡眠会让goroutine放弃对cpu的控制,当它再次获得控制权时它会检查自己是在睡觉吗?
我正试图抓住goroutines.拿这个代码:
package main
import "fmt"
var (
b1 []float64
b2 []float64
)
func main() {
go fill(&b1, 10)
go fill(&b2, 10)
fmt.Println(b1,b2)
var s string
fmt.Scanln(&s)
}
func fill(a *[]float64, n int) {
for i:=0; i<n; i++ {
*a = append(*a, rand.Float64()*100)
}
}
Run Code Online (Sandbox Code Playgroud)
如你所见,我正试图填补两片.但是当以这种方式运行时(带go fill()),它会打印两个空切片.为什么这不起作用?
不,这不是因为我的程序结束太快了.
我有这个脚本:
package main
import ("log"; "io/ioutil"; "strings")
const BASE_FILE_NAME = "abc_"
func mygoroutine(file_name string) {
log.Println("In goroutine for file", file_name)
}
func get_file_names() []string {
file_names := make([]string, 0)
files, _ := ioutil.ReadDir("./")
for _, file := range files {
if strings.HasPrefix(file.Name(), BASE_FILE_NAME) {
file_names = append(file_names, file.Name())
}
}
return file_names
}
func main() {
file_names := get_file_names()
for _, file_name := range file_names {
log.Println("Now lunching goroutine for file", file_name)
go mygoroutine(file_name)
}
log.Println("Finished launching.")
for {} …Run Code Online (Sandbox Code Playgroud) 我有更新DOM的代码.new-recipe!调用API来获取新的配方字符串.update-recipe-state接下来在屏幕中更新此状态.最后我们打电话给update-transition-buttons.
(defn- add-listener-to-recipe-button! []
"Listens to go button, creates a new recipe and displays it"
(create-click-event-listener! (dommy/sel1 :#button-start)
#(go (new-recipe!)
(<! (timeout 2000))
(update-recipe-state!)
(<! (timeout 2000))
(update-transition-buttons! "onboarding"))))
;; define your app data so that it doesn't get over-written on reload
(defonce world
(add-listener-to-recipe-button!))
Run Code Online (Sandbox Code Playgroud)
在update-transition-buttons有步骤(利用超时代码之间的一些延迟在这里),如下所示:
(defn- update-transition-buttons! [recipe-name]
"Updates the buttons with the transition names"
(go
;; Split response in list of actions by splitting on the comma
(let …Run Code Online (Sandbox Code Playgroud) 我当前正在学习GO.在学习了一些基础知识后,我一直在尝试编写一个小程序,它使用goroutine同时将网页(切片中的网址)下载到不同的文件中.这是我写的一些代码:
func downloadFromUrl(url string) {
tokens := strings.Split(url, "/")
fileName := tokens[len(tokens)-1]
// I took out the bit that download the file for testing.
fmt.Println("Downloading", url, "to", fileName)
}
Run Code Online (Sandbox Code Playgroud)
我评论了实际下载页面以进行测试的位.在我的主要功能中,我这样做:
func main() {
urls := []string{"http://www.google.com", "http://www.yahoo.com", "http://www.google.com"}
for _, url := range urls {
fmt.Println(url);
go downloadFromUrl(url);
}
}
Run Code Online (Sandbox Code Playgroud)
问题是,当我使用表达式go downloadFromUrl(url);函数downloadFromUrl不运行时.但如果我只是downloadFromUrl(url)在循环中使用它工作正常.我究竟做错了什么?我是否必须在惯例中使用频道?
我想在go(lang)中创建游戏循环,所以我尝试了这个:
package main
import (
"fmt"
// "runtime"
"sync"
"time"
)
var v = 0
var wg sync.WaitGroup
var sec = 5
func main() {
wg.Add(1)
gameLoop()
wg.Wait()
}
func gameLoop() {
time.AfterFunc(16*time.Millisecond, gameLoop)
v++
fmt.Println(v)
if v == sec*60 {
// fmt.Println("Goroutines: ", runtime.NumGoroutine())
panic("err")
wg.Done()
}
}
Run Code Online (Sandbox Code Playgroud)
该程序以62.5Hz运行(16*time.Millisecond),var sec用于wg.Done()在5秒后调用并导致var v打印300次.
调用这样panic("err")的结果:
panic: err
goroutine 314 [running]:
panic(0x493c60, 0xc420094370)
/usr/local/go/src/runtime/panic.go:500 +0x1a1
main.gameLoop()
/home/billyzaelani/Desktop/main.go:26 +0x11f
created by time.goFunc
/usr/local/go/src/time/sleep.go:154 +0x44
exit status …Run Code Online (Sandbox Code Playgroud) 为什么我在终止之前有多个goroutine,即使我关闭了resp.body,而我只使用了阻止调用?如果我不消耗resp.Body它只用一个goroutine终止.
package main
import (
"fmt"
"io/ioutil"
"net/http"
"runtime"
"time"
)
func fetch() {
client := http.Client{Timeout: time.Second * 10}
url := "http://example.com"
req, err := http.NewRequest("POST", url, nil)
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
_, err = ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
}
func main() {
fmt.Println("#Goroutines:", runtime.NumGoroutine())
fetch()
// runtime.GC()
time.Sleep(time.Second * 5)
fmt.Println("#Goroutines:", runtime.NumGoroutine())
}
Run Code Online (Sandbox Code Playgroud)
输出:
#Goroutines: 1
#Goroutines: 3
Run Code Online (Sandbox Code Playgroud) 为什么像以下这样的GO例程在使用缓冲通道时以随机顺序输出字节序列?
下面是复制错误行为的代码,其中data.csv包含1000行随机数据(大约每行100个字节)加上标题行(总共1001行)的简单CSV.
package main
import (
"bufio"
"os"
"time"
)
func main() {
var channelLength = 10000
var channel = make(chan []byte, channelLength)
go func() {
for c := range channel {
println(string(c))
}
}()
file, _ := os.Open("./data.csv")
scanner := bufio.NewScanner(file)
for scanner.Scan() {
channel <- scanner.Bytes()
}
<-time.After(time.Second * time.Duration(3600))
}
Run Code Online (Sandbox Code Playgroud)
以下是输出的前6行作为我对"断开输出"的意思的一个例子:
979,C
tharine,Vero,cveror6@blinklist.com,Female,133.153.12.53
980,Mauriz
a,Ilett,milettr7@theguardian.com,Female,226.123.252.118
981
Sher,De Laci,sdelacir8@nps.gov,Female,137.207.30.217
[...]
Run Code Online (Sandbox Code Playgroud)
另一方面,如果channelLength = 0,则代码运行平稳,因此使用无缓冲通道(前6行):
id,first_name,last_name,email,gender,ip_address
1,Hebert,Edgecumbe,hedgecumbe0@apple.com,Male,108.84.217.38
2,Minor,Lakes,mlakes1@marriott.com,Male,231.185.189.39
3,Faye,Spurdens,fspurdens2@oakley.com,Female,80.173.161.81
4,Kris,Proppers,kproppers3@gmpg.org,Male,10.80.182.51
5,Bronnie,Branchet,bbranchet4@squarespace.com,Male,118.117.0.5
[...]
Run Code Online (Sandbox Code Playgroud)
数据是随机生成的.
goroutine ×10
go ×9
append ×1
asynchronous ×1
channel ×1
clojure ×1
concurrency ×1
core.async ×1
figwheel ×1
game-loop ×1
sleep ×1
slice ×1
time ×1