I am trying to use channels to implement a kind of a worker pool. Please take a look at the code below
https://play.golang.org/p/g7aKxDoP9lf (The Go Playground)
package main
import (
"fmt"
"time"
)
func main() {
q1 := make(chan int)
fmt.Printf("worker 1\n")
go worker1(q1)
for i := 0; i < 10; i++ {
fmt.Printf("sending: %v\n", i)
q1 <- i
}
time.Sleep(time.Second)
fmt.Printf("\n\nworker 2\n")
q2 := make(chan *int)
go worker2(q2)
for i := 0; i < 10; i++ {
fmt.Printf("sending: %v\n", i)
q2 <- &i
}
time.Sleep(time.Second)
}
func worker1(qTodo <-chan int) {
var curr int
for {
select {
case curr = <-qTodo:
fmt.Printf("got: %v\n", curr)
}
}
}
func worker2(qTodo <-chan *int) {
var curr *int
for {
select {
case curr = <-qTodo:
fmt.Printf("got: %v\n", *curr)
}
}
}
Here is a sample output
worker 1
sending: 0
got: 0
sending: 1
sending: 2
got: 1
got: 2
sending: 3
sending: 4
got: 3
got: 4
sending: 5
sending: 6
got: 5
got: 6
sending: 7
sending: 8
got: 7
got: 8
sending: 9
got: 9
worker 2
sending: 0
got: 0
sending: 1
sending: 2
got: 2
got: 2
sending: 3
sending: 4
got: 4
got: 4
sending: 5
sending: 6
got: 6
got: 6
sending: 7
sending: 8
got: 8
got: 8
sending: 9
got: 10
It seems that at the time when the pointer is recieved by worker2, the value has already changed in the original variable which is reflected in the value printed.
The question is how can this be avoided? How can this be worked around?
This problem is covered in the Channels section of Effective Go. Here's a short excerpt, with the variable name changed to match your code:
The bug is that in a Go for loop, the loop variable is reused for each iteration, so the i variable is shared across all goroutines. That's not what we want. We need to make sure that i is unique for each goroutine.
It goes on to describe two solutions:
Pass the value of i as an argument to the function in the goroutine
Create a new variable in the loop and use that instead
Since your goroutine is started outside your loop, only #2 applies to your code.
The value that the received pointer points to is not what you expect because you're sending it a pointer to the same variable every time, so the worker sees whatever value that variable has at the time it dereferences the pointer. A typical way around this sort of problem is to make a copy of the variable inside the for loop and send a pointer to that. That way, you're sending a pointer to a different object every time. Try this:
for i := 0; i < 10; i++ {
fmt.Printf("sending: %v\n", i)
iCopy := i
q2 <- &iCopy
}
Related
My Project Crashed in RealmUtil.swift line 16, the codes are shown below.
Is this mean that realm return nil?
I was quite confused. Hoping to get your help.
Great Thanks!
RealmUtil.swift
15 let realm = try! Realm()
16 try! realm.write {
17 write()
18 }
detail log are as below.
It's shown in firebase, and I wasn't able to debug this in debug mode.
Crashed: com.apple.main-thread
0 libsystem_kernel.dylib 0x1978b5ec4 __pthread_kill + 8
1 libsystem_pthread.dylib 0x1977d5724 pthread_kill$VARIANT$armv81 + 216
2 libsystem_c.dylib 0x197725844 abort + 100
3 Realm 0x1041bfe30 please_report_this_error_to_help_at_realm_dot_io + 10
4 Realm 0x1041c00fc realm::util::terminate_internal(std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) + 264
5 Realm 0x1041c0270 realm::util::terminate(char const*, char const*, long, std::initializer_list<realm::util::Printable>&&) + 324
6 Realm 0x103eed0f4 realm::_impl::RealmCoordinator::advance_schema_cache(unsigned long long, unsigned long long) + 182
7 Realm 0x103fc0c2c realm::Realm::cache_new_schema() + 100
8 Realm 0x103fc1510 realm::Realm::begin_transaction() + 176
9 Realm 0x103f900e0 -[RLMRealm beginWriteTransaction] + 20
10 RealmSwift 0x10477004c $s10RealmSwift0A0V5write16withoutNotifying_xSaySo20RLMNotificationTokenCG_xyKXEtKlF + 136
11 Ig Followers 0x102da91c8 specialized static HomeViewModel.engagementAnalysis(media:) + 16 (RealmUtil.swift:16)
12 Ig Followers 0x102da9408 specialized static HomeViewModel.analysisLTS() + 4301886472 (<compiler-generated>:4301886472)
13 Ig Followers 0x102c84b2c closure #1 in closure #1 in HomeVC.getLTSData() + 4300688172 (<compiler-generated>:4300688172)
14 Ig Followers 0x102dab644 partial apply for closure #1 in closure #1 in static HomeViewModel.getLTSData2(pk:completeHandler:) + 4301895236 (<compiler-generated>:4301895236)
15 Ig Followers 0x102c9f454 thunk for #escaping #callee_guaranteed () -> () + 4300797012 (<compiler-generated>:4300797012)
added image about detail function about this problem.
crashed_function_image_click_to_see
The problem is how the optionals are being handled. The issue is here
let lts = HVMlts()!
as that code force unwraps the return value guaranteeing HVMlts will never be nil.
However if you look at the associated functions, it can in fact, return nil.
if results.count == 1 {
return results[0]
} else {
return nil
}
If the Realm filter
let results = realm.objects(HomeViewModel.self)...
returns two or more results, then that function would return nil. Likewise if there were no results then it would also return nil
In either case that nil would cause your code to crash.
It's best to safely unwrap optionals or provide default values using a nil coalescing operator. I see you've done that in other parts of your code but here are two more options.
if let lts = HVMlts() then {
//do something with lts as it's not nil
}
or
guard let lts = HVMlts() else { return }
//do something with lts
I'm a beginner at TCL and while trying to build the GCD algorithm I ran into some problems I'd like some help with:
how can I call a proc inside a proc recursively like so
proc Stein_GCD { { u 0 } { v 0 } } {
if { $v == 0 } {
puts "$u\t\t$v\t\t$v"
}
if { [expr { $v % 2 } && { $u % 2 } ] == 0 } {
return [expr 2 * ${Stein_GCD 1 0} ]
}
}
set a [Stein_GCD 2 2 ]
puts $a
as you can see, I made the proc to evaluate GCD(the code does not make any sense because I'm trying to solve an example issue), and I'm trying to recursively call the proc again to continue evaluating(notice that I made an if statement that can understand the Stein_GCD 1 0 call, yet the tcl 8.6.6 online EDA emulator says:
can't read "Stein_GCD 1 0": no such variable
while executing
"expr 2 * ${Stein_GCD 1 0} "
(procedure "Stein_GCD" line 5)
invoked from within
"Stein_GCD 2 2 "
invoked from within
"set a [Stein_GCD 2 2 ]"
(file "main.tcl" line 7)
Can you tell me how to efficiently recursively call a proc, and where was my mistake?
will gladly provide more info in the case I did a bad job at explaining.
The error can't read "Stein_GCD 1 0": indicates that you are treating the data as a single string instead of separate arguments. The problem line:
return [expr 2 * ${Stein_GCD 1 0} ]
is not written correctly. ${Stean_GCD 1 0} is not a variable.
You should have:
return [expr 2 * [Stein_GCD 1 0] ]
You want the result from Stein_GCD 1 0, so the brackets should be used.
Is there an existing function where we can pop a (key,value) pair from a map in GO? I use the word pop instead of remove because a pop would re-arrange the elements after the index where the (key,value) was removed.
As an example the following code:
package main
import "fmt"
func main() {
mapp := make(map[int]int)
fmt.Println("before removal:")
for i := 1; i < 7; i++ {
mapp[i] = i
}
fmt.Println(mapp)
delete(mapp, 2)
fmt.Println("\nafter the removal:")
for i := 1; i < 7; i++ {
fmt.Println(i, mapp[i])
}
}
Produces the following output:
before removal:
map[1:1 2:2 3:3 4:4 5:5 6:6]
after the removal:
1 1
2 0
3 3
4 4
5 5
6 6
We notice that index location 2 is empty. I would like the output to be the following:
before removal:
map[1:1 2:2 3:3 4:4 5:5 6:6]
after the removal:
1 1
2 3
3 4
4 5
5 6
Is this functionality already in Go or would I have to implement it?
I think that you are misunderstanding what a map is and how it works. You should not see it as an "array with gaps", but as a classic hash table.
And to answer your question, when you use delete(), the value is deleted from the map, the problem is how you iterate over the "values" of the map.
To help you understand:
mapp := make(map[int]int)
fmt.Println(2, mapp[2])
will print
2 0
Why ? Simply because when the requested key doesn't exist, we get the value type's zero value. In this case the value type is int, so the zero value is 0.
So, you want to see if a key exists in the map before printing it and you have to use two-value assignment, like that:
for i := 1; i < 7; i++ {
if value, exists := mapp[i]; exists {
fmt.Println(i, value)
}
}
and it will print
1 1
3 3
4 4
5 5
6 6
Not really what you want, but the closer you can get directly with maps.
You can have a look at this blog post for more information and examples.
If you really want to have an array where you can remove values, see Verran's answer and use slices instead.
From the Go documentation:
When iterating over a map with a range loop, the iteration order is not specified and is not guaranteed to be the same from one iteration to the next.
From this, it follows that there would be no way to automatically move a value up one position to fill a gap, since the key can be in a different iteration position each time you look at the values and theres no guarantee that the value mapped to 2 will slide up to 1.
If you want to do something like this, you will have to manually shift everything down one key value, something like:
for key := 2; key < len(map)-1; key++ {
map[key] = map[key+1]
}
Alternatively, you could use slices and if you know the index you need to "pop", create a new slice that omits the value:
value := slice[2]
slice = copy(slice[:2], slice[2+1:])
I am new to groovy and I am writing a program for reading numbers from an input file which has the following format
1
2 3
4 5 6
7 8 9 10
I wish to store them in a 2D array, how would I achieve it?
I have the following code so far for the read method
private read(fileName){
def count = 0
def fname = new File(fileName)
if (!fname.exists())
println "File Not Found"
else{
def input = []
def inc = 0
fname.eachLine {line->
def arr = line.split(" ")
def list = []
for (i in 1..arr.length-1) {
list.add(arr[i].toInteger())
}
input.add(list)//not sure if this is correct
inc++
}
input.each {
print it
//not sure how to reference the list
}
}
}
I am able to print the lists but I am not sure how to use the list of lists in the program (for performing other operations on it). Can anyone please help me out here?
On the input.each all you need is to iterate again in each item in the row. If it were a collection of unknown depth, then you'd need to stick to a recursive method.
Made a small change and removed the inc, since it is not needed (at least in the snippet):
fname = """1
2 3
4 5 6
7 8 9 10"""
def input = []
fname.eachLine { line->
def array = line.split(" ")
def list = []
for (item in array) {
list.add item.toInteger()
}
input.add list
}
input.each { line ->
print "items in line: "
for (item in line) {
print "$item "
}
println ""
}
Prints:
items in line: 1
items in line: 2 3
items in line: 4 5 6
items in line: 7 8 9 10
That is plain simple iteration. You can use #Tim's suggestion to make it more idiomatic in Groovy :-)
Why is the map printing out of order, and how do I get it in to order?
package main
import (
"fmt"
)
type monthsType struct {
no int
text string
}
var months = map[int]string{
1:"January", 2:"Fabruary", 3:"March", 4:"April", 5:"May", 6:"June",
7:"July", 8:"August", 9:"September", 10:"October", 11:"Novenber", 12:"December",
}
func main(){
for no, month := range months {
fmt.Print(no)
fmt.Println("-" + month)
}
}
Prints out:
10-October
7-July
1-January
9-September
4-April
5-May
2-Fabruary
12-December
11-Novenber
6-June
8-August
3-March
Code:
func DemoSortMap() (int, error) {
fmt.Println("use an array to access items by number:")
am := [2]string{"jan", "feb"}
for i, n := range am {
fmt.Printf("%2d: %s\n", i, n)
}
fmt.Println("maps are non-sorted:")
mm := map[int]string{2: "feb", 1: "jan"}
for i, n := range mm {
fmt.Printf("%2d: %s\n", i, n)
}
fmt.Println("access items via sorted list of keys::")
si := make([]int, 0, len(mm))
for i := range mm {
si = append(si, i)
}
sort.Ints(si)
for _, i := range si {
fmt.Printf("%2d: %s\n", i, mm[i])
}
return 0, nil
}
(most of it stolen from M. Summerfield's book)
output:
use an array to access items by number:
0: jan
1: feb
maps are non-sorted:
2: feb
1: jan
access items via sorted list of keys::
1: jan
2: feb
Maps are not sorted so you may use a slice to sort your map. Mark Summerfield's book "Programming in Go" explains this on page 204 and is highly recommended.
This is very late answer, but from what I have read maps are unsorted by design, and are random as one should not rely on the order.
Besides using the sort package together with a second map, one can also use the fmt.Prinln(theMap), which will print the map sorted.
fmt: print maps in key-sorted order
This will print the map typically as follows:
map[key:value
key:value
key:value
]
But this might not be what you want...
By using the fmt.Sprint one can then manipulate the string if needed.
i.e.
s := fmt.Sprint(theMap)
s1 := s[4 : len(s)-1] // remove map[ and ]
fmt.Println(s1)