Skip to main content
1 of 3
sineemore
  • 1.8k
  • 11
  • 33

Instead of trying to get a performance increase with a faster solution let's write a solid one.

The variables

var current_prime int
var prime bool
current_prime = 0

Check this out:

var a int = 0 // 0
var b int     // default int value is 0, simular to above
var c = 0     // type is int, simular to above
d := 0        // same

The latter is short and nice, I suggest you to stick to it.

You've declared the prime variable, but is first used only within the outer loop, so declare it there. Try to introduce new variables first time you need them.

The outer loop

for {
    // ...
}

Your for loop is infinite since there is no loop condition or a break statement. The current_prime will overflow and you'll start printing the same/wrong numbers.

Also, as pointed by peterSO, the first prime number is 2, so we can start with it.

for current_prime := 2; i > 0; i++ {
    // ...
}

When overflow accures the loop condition will be falsy and the loop will terminate.

To take it futher it is better not to expect int overflow and use MaxInt* constants from math package. Apart from guaranteed proper uint overflow there is nothing solid about int, so it is better not to abuse it.

The inner loop

for i := 2; i < current_prime; i++ {
    if current_prime % i == 0 {
        prime = false
        i = current_prime
    }
}

It took me a while to understand the purpose of i = current_prime line. No. This is not nice, use break to end the loop.

This one is much cleaner to me:

for i := 2; i < current_prime; i++ {
    if current_prime % i == 0 {
        prime = false
        break
    }
}

Let's take it futher. After the inner loop you test the prime variable and print the current_prime number. So when you get current_prime % i == 0 as true you already know current_prime is not a prime number and you need to continue the outer loop. For such purpose Golang has labels that perfectly solve the task:

outer:
    for prime := 2; prime > 0; prime++ {
        for i := 2; i < prime; i++ {
            if prime % i == 0 {
                continue outer
            }
        }
        fmt.Println(prime)
    }

A continue outer statement will break the inner loop and continue the outer one. When you place a label one line before the loop you may break and continue right to it. It helps escaping nested loops a lot.

Finally lets choose the appropriate types for our task. Since we don't need the signed numbers we can use uint instead of int. Also lets use uint64 directly to guaranty the maximum availiable type. Also a nice thing about unsigned numbers is that Golang guarantees that they will properly overflow so we can check for zero value to terminate the loop.

package main

import "fmt"

func main() {

outer:
    for prime := uint64(2); prime > 0; prime++ {
        for i := uint64(2); i < prime; i++ {
            if prime % i == 0 {
                continue outer
            }
        }
        fmt.Println(prime)
    }
}

Nice things about the rewrite:

  • only two variables
  • proper type is used
  • overflow is handled
sineemore
  • 1.8k
  • 11
  • 33