I have a problem with local variable "i". The second time i call nextEven, i think "i" should be intitialized back to 0. But the value "i" is saved in "makeEvengenerator()".
package main
import "fmt"
func makeEvengenerator() func() int {
i:=0
return func() (ret int) {
ret = i
i += 2
return ret
}
}
func main() {
nextEven := makeEvengenerator()
fmt.Println(nextEven())
fmt.Println(nextEven())
fmt.Println(nextEven())
}
I expected in to print out 0 0 0
Also I dont understand why everytime I call nextEven(), the code "i:=0" dont run again everytime i call the nextEven()
The second time i call nextEven, i think "i" should be intitialized back to 0
Why would it ? If you really want to reinitialize 0, then you can do:
func makeEvengenerator() func() int {
return func() (ret int) {
i := 0
ret = i
i += 2
return ret
}
}
But it would not make much sense as you usually want a closure to encapsulate a state or dependencies.
You can get some documentation and alternate examples here.
Related
This question already has an answer here:
Why I get 0 and 1 in the following golang code example with defer
(1 answer)
Closed 11 months ago.
I've been staring at this code and can't figure out the why of its behavior.
package main
import (
"fmt"
)
var i int
func example() int {
defer func() {
fmt.Println("defer")
i = 1
}()
fmt.Println("first")
return i
}
func main() {
fmt.Println(example())
fmt.Println(i)
}
At first, the expected output for me is:
first
defer
1
1
But, as you can see in the playground the actual output is:
first
defer
0
1
Is it a deferred anonymous function behavior? Nope
So, why is it printing 0?
Does defer runs after function returns?
Certainly.
So, why is it printing 0?
Because you're returning 0.
example() returns an int by value. when return i is evaluated, is current value is returned. After that return is evaluated, the defer function executes, changing the value stored at i to 1. But the 0 value is already the return value.
Go makes it possible to modify the return value of a function, but only if the return value has a name.
For example, this returns 1:
func example() (j int) {
defer func() { j = 1 }()
return 0
}
But in your case, you're not naming your return variable, so you can't modify it in a defer.
Hi I want to write a generic function to trace error message when a function returns error. So I wrote this:
func TraceError1(err *error) {
if err != nil && *err != nil {
pc := make([]uintptr, 15)
n := runtime.Callers(2, pc)
frames := runtime.CallersFrames(pc[:n])
frame, _ := frames.Next()
fmt.Printf("%s:%d %s\n", frame.File, frame.Line, frame.Function)
}
}
func TraceError2(err error) {
if err != nil {
pc := make([]uintptr, 15)
n := runtime.Callers(2, pc)
frames := runtime.CallersFrames(pc[:n])
frame, _ := frames.Next()
fmt.Printf("%s:%d %s\n", frame.File, frame.Line, frame.Function)
}
}
func foo() (err error) {
defer TraceError1(&err)
defer TraceError2(err)
fmt.Println("do something")
return fmt.Errorf("haha")
}
TraceError1 works but TraceError2 didn't. In my understanding, error is an interface so it is a pointer/address, why do I need to pass its address? Why TraceError2 cannot work? Thanks.
In case of TraceError1 you are passing a pointer to the named return value err. The pointer is non-nil, but the value it points at (err) is nil (at the time of defer). However, it is not yet evaluated (dereferenced) because TraceError1 has not yet been called. By the time the function does run (after foo returns) and the pointer gets dereferenced, the value of err has been updated (by the return statement inside foo).
However, in case of TraceError2, a nil interface value is passed, which will stay nil even when TraceError2 executes eventually.
Here is a simpler example:
package main
import "fmt"
func intByValue(i int) {
fmt.Printf("i = %d\n", i)
// ^--- `i` is an integer value
// --- whatever i was passed to the function, gets printed
}
func intByRef(i *int) {
var v int = *i // i is a pointer to an int, which gets dereferenced here
// the *address* where the actual value resides was passed
// while the address stays the same, its value can change before
// i is dereferenced, and its value stored in v.
fmt.Printf("i = %d\n", v)
}
func main() {
var i int
defer intByValue(i) // passed the *value* of i, which is 0 right now
defer intByRef(&i) // passed a *pointer* to i, which contains 0 right now
i = 100 // before intByRef could "dereference" its argument, the value that it
// contained has been updated
// intByRef gets called, dereferences the value, finds 100, prints it.
// intByValue gets called, finds 0, prints it
// result should be:
// i = 100
// i = 0
}
So unfortunately, if you want the ability to update the error (e.g. by returning a named return value) before it gets used by the deferred function, you are going to have to pass around pointers to the variable.
In other words, TraceError2 is simply not suited for your use case.
Edit: use correct terminology and (questionably) improve example code.
As go blog explained
The behavior of defer statements is straightforward and predictable.
There are three simple rules:
A deferred function's arguments are evaluated when the defer statement is evaluated.
Deferred function calls are executed in Last In First Out order after the surrounding function returns.
Deferred functions may read and assign to the returning function's named return values.
According to first point, when you call defer TraceError2(err) , that err = nil and that is the value pass to the TraceError2 function.
TraceError1(err *error) works because it is getting a pointer to err, and that pointer value is assigned before defer func TraceError1 is executed.
Simple example code to explain the behaviour.
package main
import (
"fmt"
"runtime"
)
func main() {
i := 0
defer func(i int) {
fmt.Printf("%d\n",i) //Output: 0
}(i)
defer func(i *int) {
defer fmt.Printf("%d\n",*i) //Output: 1
}(&i)
i++
}
So im getting further into using golang and looking more into the concurrency it offers. I decided to try to use go routines to implement permutations of strings in a phone number.
I am running into issues using sync.WaitGroup to coordinate the go routines that i have been using. the specific error being:
WaitGroup is reused before previous Wait has returned
the code being:
main.go
package main
import (
"fmt"
"sync"
"github.com/sbiscigl/phonenumberperm/intstack"
"github.com/sbiscigl/phonenumberperm/permutations"
)
var wg sync.WaitGroup
func main() {
num := []int{2, 7, 1, 4, 5, 5, 2}
stack := intstack.New(num)
permutationChannel := make(chan string)
wg.Add(1)
go permutations.ThreadSafeCalcWords(stack, "", permutationChannel, &wg)
wg.Wait()
/*Then consume, but not implimented*/
}
permutations/perm.go
package permutations
import (
"fmt"
"sync"
"github.com/sbiscigl/phonenumberperm/intstack"
)
var letterMap = map[int][]string{
2: []string{"a", "b", "c"},
3: []string{"d", "e", "f"},
4: []string{"g", "h", "i"},
5: []string{"j", "k", "l"},
6: []string{"m", "n", "o"},
7: []string{"p", "q", "r", "s"},
8: []string{"t", "u", "v"},
9: []string{"w", "x", "y", "z"},
}
func ThreadSafeCalcWords(s intstack.IntStack, word string, ch chan<- string,
wg *sync.WaitGroup) {
if s.IsEmpty() {
ch <- fmt.Sprint(word)
wg.Done()
} else {
/*Check to see if the values are 1 or zero as they*/
/*have no letters associated with them*/
if s.Peek() == 1 || s.Peek() == 0 {
wg.Done()
s.Pop()
wg.Add(1)
go ThreadSafeCalcWords(s, word, ch, wg)
} else {
wg.Done()
for _, letter := range letterMap[s.Pop()] {
wg.Add(1)
go ThreadSafeCalcWords(s, word+letter, ch, wg)
}
}
}
}
intstack/intstack.go
package intstack
import "fmt"
const (
maxSize = 100
)
/*IntStack implimentaiton of a stack for integers*/
type IntStack struct {
valueList []int
maxSize int
}
/*New returns bew instace of IntStack*/
func New(nums []int) IntStack {
return IntStack{
valueList: nums,
maxSize: maxSize,
}
}
/*Pop pops the top value off the stack*/
func (s *IntStack) Pop() int {
var val int
if !s.IsEmpty() {
val = s.valueList[0]
s.valueList = s.valueList[1:]
} else {
fmt.Println("stack is empty")
}
return val
}
/*Peek returns top value*/
func (s IntStack) Peek() int {
return s.valueList[0]
}
/*IsEmpty checks if the stack is empty*/
func (s IntStack) IsEmpty() bool {
if len(s.valueList) > 0 {
return false
}
return true
}
/*Print prints out the contents of the stack*/
func (s IntStack) Print() {
for _, element := range s.valueList {
fmt.Print(element)
}
fmt.Print("\n")
}
So after research that line is called during wg.Wait() or rathe wait groups wait function. I tried to replicate with a smaller program, but could not. My hypothesis is that once it reaches the the Wait() after it calls the the go routine, that we can no longer edit the wait group, but that sounds wrong. any insight into why this would be happening would be helpful
repo for refrence can be found at: https://github.com/sbiscigl/phonenumberperm
In your recursive cases in ThreadSafeCalcWords, you're calling wg.Done before calling wg.Add. That means that the wg can drop down to 0 (which will trigger the Wait to complete) before you actually finish all the work. Calling Add again while the Wait is still in the process of resolving is what triggers the error, but more importantly, it probably just plain isn't what you want.
Change the order of operations so that you always Add any new work before doing Done on the existing work, and the Wait won't trigger prematurely. The simplest way to accomplish this would probably be a single call to wg.Done() at the bottom of the function, or a single defer at the top, and removing all the others.
I want a set of code to be executed until user explicitly wants to exit the function. For eg: when a user runs the program, he will see 2 options:
Run again
Exit
this will be achieved using switch case structure. Here if user presses 1, set of functions associated with 1 will execute and if user presses 2, the program will exit. How should i achieve this scenario in golang ? In java, i believe this could be done using do while structure but go doesn't support do while loop. Following is my code which i tried but this goes in a infinite loop:
func sample() {
var i = 1
for i > 0 {
fmt.Println("Press 1 to run")
fmt.Println("Press 2 to exit")
var input string
inpt, _ := fmt.Scanln(&input)
switch inpt {
case 1:
fmt.Println("hi")
case 2:
os.Exit(2)
default:
fmt.Println("def")
}
}
}
The program irrespective of the input, prints only "hi". Could someone please correct me what wrong i am doing here ?
Thanks.
A do..while can more directly be emulated in Go with a for loop using a bool loop variable seeded with true.
for ok := true; ok; ok = EXPR { }
is more or less directly equivalent to
do { } while(EXPR)
So in your case:
var input int
for ok := true; ok; ok = (input != 2) {
n, err := fmt.Scanln(&input)
if n < 1 || err != nil {
fmt.Println("invalid input")
break
}
switch input {
case 1:
fmt.Println("hi")
case 2:
// Do nothing (we want to exit the loop)
// In a real program this could be cleanup
default:
fmt.Println("def")
}
}
Edit: Playground (with a dummied-out Stdin)
Though, admittedly, in this case it's probably overall clearer to just explicitly call (labelled) break, return, or os.Exit in the loop.
When this question was asked this was a better answer for this specific scenario (little did I know this would be the #1 result when searching Google for "do while loop golang"). For answering this question generically please see #LinearZoetrope's answer below.
Wrap your function in a for loop:
package main
import (
"fmt"
"os"
)
func main() {
fmt.Println("Press 1 to run")
fmt.Println("Press 2 to exit")
for {
sample()
}
}
func sample() {
var input int
n, err := fmt.Scanln(&input)
if n < 1 || err != nil {
fmt.Println("invalid input")
return
}
switch input {
case 1:
fmt.Println("hi")
case 2:
os.Exit(2)
default:
fmt.Println("def")
}
}
A for loop without any declarations is equivalent to a while loop in other C-like languages. Check out the Effective Go documentation which covers the for loop.
The do...while in go can be this:
func main() {
var value int
for {
value++
fmt.Println(value)
if value%6 != 0 {
break
}
}
}
a while loop in Go can be as easy as this:
package main
import `fmt`
func main() {
for {
var number float64
fmt.Print(`insert an Integer eq or gr than 10!!!`)
fmt.Scanf(`%f`, &number)
if number >= 10 { break }
fmt.Println(`sorry the number is lower than 10....type again!!!`)
}
Conside to use "for-break" as "do-while".
foo.go
package main
import (
"fmt"
)
func main() {
i := 0
for {
i++
if i > 10 {
break
}
fmt.Printf("%v ", i)
}
fmt.Println()
}
shell
$ go run foo.go
1 2 3 4 5 6 7 8 9 10
Maybe not what you're looking for, but if you're trying to do something like this:
int i = 0;
while (i < 10) {
cout << "incrementing i now" << endl;
i++
}
cout << "done"
You'll have to do something like this in go:
var i = 0
fmt.Println(i)
for {
if i < 10 {
fmt.Println("incrementing i now")
i++
} else {
break
}
}
fmt.Println("done")
sum := 1
for sum < 1000 {
sum += sum
}
Explanation :
The basic for loop has three components separated by semicolons:
-the init statement: executed before the first iteration.
-the condition expression: evaluated before every iteration
-the post statement: executed at the end of every iteration
The init and post statements are optional.
So you can just put in the condition expression.
// While (CONDITION = true){
//code to execute ....}
//In go :
for CONDITION = true {
//code to execute}
This is one of the cleanest ways:
num := 10
for num > 0 {
// do stuff here
num--
}
Using Google Go, I'm trying to sync multiple threads performing an iterative filter on an image. My code basically works like outlined here:
func filter(src *image.Image, dest *image.Image, start, end, runs int, barrier ??) {
for i:= 0; i < runs; i++ {
// ... do image manipulation ...
// barrier.Await() would work here
if start == 1 {
// the first thread switches the images for the next iteration step
switchImgs(src, dest)
}
// barrier.Await() again
}
}
func main() {
//...
barrier := sync.BarrierNew(numberOfThreads)
for i := 0; i < numberOfThreads; i++ {
go filter(..., barrier)
}
The problem is that I would need a reusable barrier quite like Java's CyclicBarrier, setting the number of threads as its counter value. Unfortunately, the only implementation similar to a barrier I have found is sync.WaitGroup. The WaitGroup however cannot be reset atomically to it's previous counter value. It only offers a normal Wait() function that does not reset the counter value.
Is there any "Go idiomatic" way of achieving what I want or should I rather implement my own CyclicBarrier? Thanks a lot for your help!
You can use sync.Cond to implement CyclicBarrier, see source code of java's CyclicBarrier
Here is a minimized go version of CyclicBarrier (no timeout, no thread interrupts):
http://play.golang.org/p/5JSNTm0BLe
type CyclicBarrier struct {
generation int
count int
parties int
trip *sync.Cond
}
func (b *CyclicBarrier) nextGeneration() {
// signal completion of last generation
b.trip.Broadcast()
b.count = b.parties
// set up next generation
b.generation++
}
func (b *CyclicBarrier) Await() {
b.trip.L.Lock()
defer b.trip.L.Unlock()
generation := b.generation
b.count--
index := b.count
//println(index)
if index == 0 {
b.nextGeneration()
} else {
for generation == b.generation {
//wait for current generation complete
b.trip.Wait()
}
}
}
func NewCyclicBarrier(num int) *CyclicBarrier {
b := CyclicBarrier{}
b.count = num
b.parties = num
b.trip = sync.NewCond(&sync.Mutex{})
return &b
}
I don't fully understand how CyclicBarrier works, so excuse me if I'm way off.
A very simple wrapper around SyncGroup should do the job, for example:
type Barrier struct {
NumOfThreads int
wg sync.WaitGroup
}
func NewBarrier(num int) (b *Barrier) {
b = &Barrier{NumOfThreads: num}
b.wg.Add(num)
return
}
func (b *Barrier) Await() {
b.wg.Wait()
b.wg.Add(b.NumOfThreads)
}
func (b *Barrier) Done() {
b.wg.Done()
}
func filter(src *image.Image, dest *image.Image, start, end, runs int, barrier *Barrier) {
for i := 0; i < runs; i++ {
// ... do image manipulation ...
//this filter is done, say so by using b.Done()
b.Done()
b.Await()
if start == 1 {
// the first thread switches the images for the next iteration step
//switchImgs(src, dest)
}
b.Done()
b.Await()
}
}
func main() {
barrier := NewBarrier(5)
for i := 0; i < barrier.NumOfThreads; i++ {
go filter(1, barrier)
}
}