is access to single variable from routines integrity safe? [closed] - go

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
Given such a code:
type Test struct {
V int
}
func (t *Test) t() {
t.V += 1
}
func main() {
t := Test{}
for i := 1; i <= 1000000; i++ {
go t.t()
}
for {
fmt.Println(t.V)
time.Sleep(3 * time.Second)
}
}
I hope it is clear, why do I do this test. And the result is never 1000000. It always prints number less than 1000000.. So, only go channels can I use to solve it ?
Why don't I have 1000000 in result ? How to get 1000000 ?

is access to single variable from routines integrity safe?
No. Everything that is racy is not safe. Under no circumstances. Not if is a single variable, not if accessed by an odd number of goroutines and not on Mondays. Never.

Related

Why there is a data race [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 months ago.
Improve this question
I was reading Dave Cheney's post https://dave.cheney.net/2015/11/18/wednesday-pop-quiz-spot-the-race, but couldn't understand why the example contains data race. Can someone explain it to me?
Here's the relevant code from the blog post:
func (rpc *RPC) compute() {
time.Sleep(time.Second)
rpc.result = 42 /* W */
close(rpc.done)
}
func (RPC) version() int {
return 1
}
⋮
go rpc.compute()
version := rpc.version() /* R */
<-rpc.done
The goroutine modifies the caller's rpc.result field at the line notated by /* W */. This is the easy part to understand.
The method call at the line notated by /* R */ is syntactic sugar for (*rpc).version(). The receiver value is copied on the method call, including the result field. The read is concurrent with the write at /* W */ and is therefore a data race. Although the program does not do anything with the copied result field, it's still a data race.
Fix by changing the version() method to use pointer receiver:
func (*RPC) version() int {
return 1
}

Golang use LIKE inside IF statement best practice [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
if i have many option to be filter in IF statement, can i use some function like this?
s1 := "lorem ipsum"
sum := 0
for _, v := range s1 {
if string(v) like ("a","i","u","e","o") {
sum+=1
}
}
You can use switch statement.
Switch supports multiple matches
switch string(v) {
case "a","i","u","e","o":
sum+=1
}
Tried it in the playground - https://play.golang.org/p/QRYhEDA7EUZ

lock appending slice,no lock reading, so i can get the new length, but no element? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
when i wrote golang parallel benchmarks for some real codes,i got 1 error.
For example, the variable f will be nil in the func 1,why?
type foo struct {
name string
}
var s []*foo
race func 1:
for {
// no lock
length := len(s) // typo, it should be len(s) - 1
f := s[length]
fmt.Println(f.name)
}
race func 2:
for {
// lock
mu.Lock()
s = append(s, &foo{})
mu.Unlock()
}
mutexes does not affect calls between locks and unlocks (they do not become atomic, thats not possible for all operations), mutex is what prevents data race but you have to use it for reading and writing and you have to use same instance of mutex on both sides. So this code is safe:
type SyncSlice struct {
inner []int
m sync.Mutex
}
func (s *SyncSlice) Append(elem int) {
s.m.Lock()
s.inner = append(s.inner, elem)
s.m.Unlock()
}
func (s *SyncSlice) Len() int {
s.m.Lock()
defer s.m.Unlock() // as we have to unlock after returning
return len(s.inner)
}
func (s *SyncSlice) Get(i int) int {
s.m.Lock()
defer s.m.Unlock() // as we have to unlock after returning
return s.inner[i]
}
func (s *SyncSlice) Set(i, value int) {
s.m.Lock()
s.inner[i] = value
s.m.Unlock()
}
Though it is safe only if you use methods and not fields directly. You also have to use same instance of slice, so gorotines have to have acces to pointer of SyncSlice

How to store dynamic input in maps [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
In Go, how should I put dynamic/user input in maps
func main() {
mapp := make(map[int]string)
for i := 0; i < 5; i++ {
fmt.Scanf("%d %s", &mapp[i], &mapp[i])
}
fmt.Print(mapp)
}
You can't create a key-value pair on a map like that.
What you can do, is store the input in variables, and then create a map key-value pair with the input. Like this:
for i := 0 ; i < 5 ; i++ {
var num int
var text string
fmt.Scanf("%d %s",&num,&text)
mapp[num] = text
}

Idiomatic way of handling a goroutine with one "return" value? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
Imagine I want to write a function that returns a random number divided by 2:
func randomIntInHalf() int {
return rand.Int() / 2
}
But then I decide I want to build this function for concurrency so I end up with:
func randomIntInHalf(c chan<- int) {
c <- rand.Int() / 2
}
func main() {
// Generate 10 random ints in parallel
amount := 10
c := make(chan int, amount)
for i := 0; i < amount; i++ {
go randomIntInHalf(c)
}
for i := 0; i < amount; i++ {
fmt.Println(<-c)
}
close(c)
}
I see some issues with this approach. For example, I require the caller to close the channel when it's done generating, making it possible that someone might call the function and leave the channel open indefinitely. It was sort of my understanding that you always want the sender to close the channel. A) is that true and b) is it even possible in this case? Is there a better way to write this code or approach this problem?
And, generally, is there a better, idiomatic approach for running a function in a parallel that only ever writes 1 (or a known N) value to the channel?
Thanks.
You do not need to close channels. Once it goes out of scope, it will be garbage collected. Closing a channel is usually used to send a done notification to the listener. So it is not even possible in your case.
Yours is an idiomatic approach for what you're trying to achieve, but not the only one. Some others (not necessarily idiomatic) that I can think of are:
You can use a shared data structure and populate that from multiple goroutines with explicit synchronization,
You can keep a separate result for each goroutine, and pass in a pointer to it. Each goroutine sets its result without a need for synchronization, and when everything is done, the caller works with the results.

Resources