Are there more small POCs or small projects I can learn more golang?

168 views
Skip to first unread message

Jan Carlo Viray

unread,
Sep 5, 2014, 10:13:23 PM9/5/14
to golan...@googlegroups.com
I'm fairly new to golang (coming from Node.js, PHP) and the conventions and ways of doing things are somewhat new and different to me.

I'm wondering if there are resources where I can learn from POCs or prototypes people have created like webservers, apis, auth, and etc.

I just started with mine here... fairly small though.


and I've been trying to answer Project Euler questions so I can learn more.


But, that is me in my newb way of doing things. Maybe you guys can edit some of my codes for best practices or point me to some resources?

Thanks!

(my first post btw!)

Sjon Kosse

unread,
Sep 5, 2014, 10:35:00 PM9/5/14
to golan...@googlegroups.com
Just looking at the first few Project Euler solutions on your Github page it seems you are missing out on named returns.
In the first file you have a function with return type []int.
You initialize it, result := []int{}
And then return it,
return result
This is highly redundant, just make the function in the shape,
func fun() (result []int) {
    return
}
Examples like this are all over it.

Caleb Spare

unread,
Sep 5, 2014, 10:43:55 PM9/5/14
to Sjon Kosse, golang-nuts
Don't go too crazy with named returns. I would not use them just to
avoid declaring a variable in the body of the function. As the code
review comments wiki page[0] says:

"Naked returns are okay if the function is a handful of lines. Once
it's a medium-sized function, be explicit with your return values.
Corollary: it's not worth it to name result parameters just because it
enables you to use naked returns. Clarity of docs is always more
important than saving a line or two in your function."

Also: it's fine to initialize slices as nil if you're going to be
appending to them:

var result []int
for ... {
result = append(result, ...)
}

[0] https://code.google.com/p/go-wiki/wiki/CodeReviewComments#Named_Result_Parameters
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

peterGo

unread,
Sep 6, 2014, 1:53:51 PM9/6/14
to golan...@googlegroups.com
Jan,

I took a quick look at your solution for Project Euler, Problem 1, Multiples of 3 and 5, 2014-08-31T19:58:43-07:00.

https://github.com/jancarloviray/project-euler-in-golang/blob/master/problem1.go

If I ask you to find the sum of all the multiples of 3 or 5 below 2,147,483,647 what happens? Is the answer correct for both of $GOARCH=386 and $GOARCH=amd64? How long does it take? How much memory does it use?

The size of built-in type int is implementation dependent and is either 32 or 64 bits. Integer operations +, -, *, and << may overflow.

If the capacity of the slice is not large enough to fit the additional values, append allocates a new, sufficiently large underlying array that fits both the existing slice elements and the additional values and has room to grow before needing another reallocation. Otherwise, append re-uses the underlying array. Therefore, if we can reasonably estimate the final slice capacity, make an initial allocation. For example,

func getMultiples(cap int) []int {
  // worst: zero allocation
  result := []int{}
  // good: estimated allocation, rounded up
  result := make([]int, 0, (cap/3)+(cap/5))
  // best: precise allocation
  result := make([]int, 0, (cap/3)+(cap/5)-(cap/(3*5)))
// . . .
}

cap = 1000
result := []int{}
BenchmarkViray       20000         98694 ns/op        8184 B/op           9 allocs/op
result := make([]int, 0, (cap/3)+(cap/5)-(cap/(3*5)))
BenchmarkViray       30000         54595 ns/op        4096 B/op           1 allocs/op

The use of a list as a temporary intermediate result is unnecessary and expensive. For example, simply write,

func getSumMultiples1(cap int) (sum int) {
  for i := 0; i < cap; i++ {
    if i%3 == 0 || i%5 == 0 {
      sum += i
    }
  }
  return sum
}

cap = 1000
list
BenchmarkViray       20000         98694 ns/op        8184 B/op           9 allocs/op
loop
BenchmarkViray1      100000         13744 ns/op           0 B/op           0 allocs/op

Of course, we could replace the loop by arithmetic, making sure that we don't double count. Note that:

0 + 3 + 6 + 9 + 12 = 3 * (1 + 2 + 3 + 4) =  3 * (4 * (4 + 1) / 2) = 3 * 10 = 30

For example,

http://play.golang.org/p/F4oKIpqjn-

cap or limit = 1000
list
BenchmarkViray       20000         98694 ns/op        8184 B/op           9 allocs/op
arithmetic
BenchmarkEuler1    20000000            60.8 ns/op           0 B/op           0 allocs/op

And we can correctly handle huge numbers with ease.

huge limit = 1<<31 - 1 = 2,147,483,647; sum = 1,076,060,070,465,310,994
BenchmarkEuler1Huge    20000000    64.6 ns/op    0 B/op    0 allocs/op

References:

Problem 1 - Project Euler
https://projecteuler.net/problem=1

Multiples of 3 and 5

The Go Programming Language Specification
http://golang.org/ref/spec

Numeric types

Integer overflow

Making slices, maps and channels

Appending to and copying slices

The Go Blog
Arrays, slices (and strings): The mechanics of 'append'
http://blog.golang.org/slices

Make

Append: The built-in function

1 + 2 + 3 + 4 + ⋯
http://en.wikipedia.org/wiki/1_%2B_2_%2B_3_%2B_4_%2B_%E2%8B%AF

Partial sums

Peter

Jan Carlo Viray

unread,
Sep 6, 2014, 4:33:42 PM9/6/14
to golan...@googlegroups.com
Wow. Very thorough.

I love the benchmark comparisons!

As a Golang newb, this is rich in advice and good for my underlying foundation on building Golang apps.

Thanks Peter!!!

peterGo

unread,
Sep 6, 2014, 9:10:36 PM9/6/14
to golan...@googlegroups.com
Jan,

I took a look at your solution for Project Euler, Problem 2, Even Fibonacci numbers, as of 2014-08-31T21:50:28-07:00.

https://github.com/jancarloviray/project-euler-in-golang/blob/master/problem2.go

http://play.golang.org/p/lcv1VYSHc1

That's a lot of complicated code that takes a long time to run.

Code should be written to be read. Keep it short, simple, and to the point.

Every third number of the Fibonacci sequence, starting with two, is even. Simply sum these numbers. For example,

http://play.golang.org/p/F2SZREfoxE

As a concession to speed the inner loop was unrolled. The code is much shorter, much simpler, and much faster. For example,

BenchmarkViray      200000          7269 ns/op         528 B/op           7 allocs/op
BenchmarkEuler2    20000000            58.5 ns/op           0 B/op           0 allocs/op

References:

Fibonacci number
http://en.wikipedia.org/wiki/Fibonacci_number

Divisibility properties

Peter
Reply all
Reply to author
Forward
0 new messages