Golang Documentation¶
Observations on Golang¶
Type-Safe
Memory-Safe
Garbage-Collected
The combination of threads and garbage-collection is particularly interesting. * You don’t need to figure out when a thread was using an object.
Golang has always been said to be simple. What, 50 keywords?
The Golang Tutorial¶
@3m So I am supposed to take the Golang tutorial and then read Effective Go before I proceed. Will do that.
My friend Karthikeyan recommended Caleb Doxsey’s An Introduction to Programming in Go, which is available for free at that link. However, I will shelve perfection and completion in the language (for now), and I will focus on the official tutorial.
Note
All code for this tutorial is in the same repository as these notes, but I will be including the code here as I go along.
Additionally, the section on languages/golang will be a better segue into the language.
In the folder golang, I am going to store all the go code I write to learn the language. It won’t have anything to do with this course, but well.
Observations as a Pythonista¶
W00t! I am not writing semi-colons.
Braces are okay. I can live with those.
import uses quotes. I was just telling someone about this yesterday.
2009-11-10 23:00:00 UTC is Golang’s Birthday, apparently.
- The way go prints out the timestamp when I use
time.Now()
is so weird. What are those extra numbers? It has the timezone, and that is great. But it also has something akin to
m=+0.00086191
. What is that?
- The way go prints out the timestamp when I use
- Every Go Program is made up of Packages?
Not everyone realizes that Python is so similar. Every python “object” is an “object”, complete with its own constructor and all.
Note to self: You can preach all the language agnosticism you want, but you cannot take the snake out of the snake charmer’s basket.
1 2 3 4 5 6 7 8 9 10 11 | package main
import (
"fmt"
"math/rand"
)
func main() {
fmt.Println("My favorite number is ", rand.Intn(10))
}
|
Wait. The output is always the same! The tour page says this:
Note: The environment in which these programs are executed is deterministic,so each time you run the example program rand.Intn will return the same number.(To see a different number, seed the number generator; see rand.Seed.Time is constant in the playground, so you will need to use something else as the seed.)
Also, so importing math/rand
allows me to use rand at the global level.
1 2 3 4 5 6 7 8 9 10 11 | package main
import (
"fmt"
"math/rand"
)
func main() {
rand.Seed(1091234017)
fmt.Println("My favorite number is ", rand.Intn(10))
}
|
Huh. The output remains constant every time I execute. So true random number generation is not possible here? I wonder what Python does. I guess it uses something the timestamp to generate the seed each time. You learn something new!
Go uses tabs! Not spaces. Heh. Pied Piper should have used Golang.
1 2 3 4 5 6 7 8 9 10 | package main
import (
"fmt"
"math"
)
func main() {
fmt.Println(math.Pi)
}
|
So Go only exposes those variables that start with a capital first letter? Works for me.
Go’s types come **after** the variable name. I like this, to be honest.
Oh wow. That article on declarations is insane. I can see why Python’s
type hints took the x: int
form now.
a, b := 1, 2
seems to be the way to define variable without declaring their
type. The types are implied from the variables on the right. This is not
usable outside of a function since every statement must begin with a keyword.
1 2 3 4 5 6 7 8 9 10 11 12 13 | package main
import "fmt"
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return
}
func main() {
fmt.Println(split(17))
}
|
Naming the return variables allows you to return them implicitly. I am not so certain I would use that. Cannot see what it is useful. Perhaps in a way so I can keep track of the returnable variable(s).
Go’s types are interesting.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | package main
import (
"fmt"
"math/cmplx"
)
var (
ToBe bool = false
MaxInt uint64 = 1<<64 - 1
z complex128 = cmplx.Sqrt(-5 + 12i)
)
func main() {
fmt.Printf("Type: %T Value: %v\n", ToBe, ToBe)
fmt.Printf("Type: %T Value: %v\n", MaxInt, MaxInt)
fmt.Printf("Type: %T Value: %v\n", z, z)
}
|
And the supported types are:
bool
string
int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
byte // alias for uint8
rune // alias for int32
// represents a Unicode code point
float32 float64
complex64 complex128
Go sets initial values to variables. They are either 0
, false
or ""
depending
upon the type.
Go assignment between items of different type requires an explicit conversion. This is done through the type functions that perform the type casting.
The :=
and the var =
ways of declaring variables perform type inference,
as noted above.
Go supports immutable const
. These can infer types as well. Constants can
be character, string, boolean, or numeric values.
Looney Loopy Looping¶
1 2 3 4 5 6 7 8 9 10 11 | package main
import "fmt"
func main() {
sum := 0
for i := 0; i < 10; i++ {
sum += i
}
fmt.Println(sum)
}
|
Ah, those old C-variety loops. Braces are always required. No parentheses.
Interesting. The for
can be turned into a while
-varient by just omitting
the instantiation and the increment.
C’s while is spelled for in Go,
LOL.
Conditionals¶
Interesting why loops are introduced before conditionals. Is it easier to grok?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | package main
import (
"fmt"
"math"
)
func sqrt(x float64) string {
if x < 0 {
return sqrt(-x) + "i"
} else {
return fmt.Sprint(math.Sqrt(x))
}
}
func main() {
fmt.Println(sqrt(2), sqrt(-16))
}
|
Hmm. fmt.Sprint()
does string typecasting, does it?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package main
import (
"fmt"
"math"
)
func pow(x, n, lim float64) float64 {
if v := math.Pow(x, n); v < lim {
return v
}
return lim
}
func main() {
fmt.Println(
pow(3, 2, 10),
pow(3, 3, 20),
)
}
|
Wait, so := is sort of the walrus operator!! W00t.
Loops don’t need parentheses here. That’s good.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package main
import "fmt"
func main() {
sum := 0
for i := 0; i < 10; i++ {
sum += i
}
fmt.Println(sum)
for sum < 1000 {
sum += 100
}
fmt.Println(sum)
for {
fmt.Println("lol infinite loops")
}
}
|
The initialization and increment are optional, so there is no need for a while or a do-while loop here. Good.
That’s hilarious. If only my old CS teacher Vasanth could see my face now.
**Go’s Conditional’s have the *walrus operator*?!**
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package main
import (
"fmt"
"math"
)
func pow(x, n, lim float64) float64 {
if v := math.Pow(x, n); v < lim {
return v
}
return lim
}
func main() {
fmt.Println(
pow(3, 2, 10),
pow(3, 3, 10),
)
}
|
I am sold.
The variable defined in the if
statement isn’t accessible outside the statement,
but variables defined within the blocks are accessible outside the blog.
Such a weird decision. I mean, even Python does this but it is very weird.