Go Crash Course (Part 2)
We are going to cover syntax in this section. The syntax is an essential part of programming languages. Some are similar to others. Some are distinctive into themselves. You can go to the previous section where there is the installation instruction if Go is not yet installed on your system.
Variables
package main import "fmt" var number, text = 9, "Lorem ipsum." func printNumber() { const pi float64 = 3.141592653589793 fmt.Println(number) fmt.Println(pi) } func printText(text string) { fmt.Println(text) } func main() { local := true printNumber() printText(text) fmt.Println(local) }
The var
statement declares a list of variables. It can include initializers, one per variable. Inside a function, the :=
short assignment statement can be used in place of a var
declaration with implicit type.
Constants are declared like variables, but with the const
keyword, and cannot be declared using the :=
syntax.
As we can see, number and text are global variables because they are defined outside of a function and on the top of the program. They can be accessed inside any of the functions defined for the program.
The boolean local
variable is a local variable inside the main
function. It can be only accessed inside the main
function.
We printed the text
variable in the printText
function. The variable has the same name as the global one. But the one that we printed is an argument variable. It was overwritten.
Types
package main import ( "fmt" "unsafe" ) func main() { var global bool var text string = "Lorem ipsum." var negative int = -9 // int8 int16 int32 int64 var positive uint = 9 // uint8 uint16 uint32 uint64 var address uintptr = uintptr(unsafe.Pointer(&global)) var ascii byte = 'a' // alias for uint8 var unicode rune = 'Ā' // alias for int32 var pi float32 = 3.141592653589793 // float32 float64 var fullPi float64 = float64(pi) var complicated complex64 = 1 + 1i // complex64 complex128 inference := 1 + complicated fmt.Println(global) fmt.Println(text) fmt.Println(negative) fmt.Println(positive) fmt.Println(address) fmt.Println(ascii) fmt.Println(unicode) fmt.Println(pi) fmt.Println(fullPi) fmt.Println(complicated) fmt.Println(inference) }
Here is the output.
false Lorem ipsum. -9 9 824634117815 97 256 3.1415927 3.1415927410125732 (1+1i) (2+1i)
We didn't initialize the value for the global
variable. The default or zero value for boolean is false, 0 for numerics, and "" (the empty string) for strings.
The difference between int
(signed integer) and uint
(unsigned integer) is it can't handle negative value and has a larger maximum value for unsigned one.
The int
, uint
, and uintptr
types are usually 32 bits wide on 32-bit systems and 64 bits wide on 64-bit systems. The number appended after the type such as int8
, int16
, and so on represents bits or size. 8 bits is equal to 1 byte.
The uintptr
type is to store the address in number. The value is the pointer address but in an integer format.
Take a look at the pi
variable. We can't store or print the actual value if the size is not enough. Then we cast float32
to float64
for fullPi
to store the actual value.
The complex (complex64
or complex128
) data type is to store a real and imaginary number (i
symbol) of float. float32
for complex64
and float64
for complex128
.
It will cast the data type automatically for shorthand. Refer to the inference
variable.
The byte
type is an alias for uint8
. The rune
type is an alias for int32
. The byte is to store ASCII characters in number (0-255). The rune is to store UNICODE characters in number (-231 to 231 -1).
Pointer
package main import "fmt" func main() { number := 9 pointer := &number fmt.Println(*pointer) fmt.Println(pointer) *pointer = number + 1 fmt.Println(number) }
The pointer is to store the address of a variable. The &
is used to get the address of the variable. The *
is used to present the value from the address of the pointed variable.
We can see that we did increment on the *pointer
variable and it applied to the number
variable.
Struct
package main import "fmt" type person struct { name string age int } func main() { p1 := person{ "John Doe", 1e1, } p2 := person{ age: 999, } p1.age += 8 fmt.Println(p1) fmt.Println(p1.name, "is", p1.age, "years old.") fmt.Println(p2) }
A struct
is a collection of fields.
Array
package main import "fmt" func main() { hello := [2]string{ "Hello", "World!", } primes := []int{2, 3, 5} fmt.Println(hello) fmt.Println(primes) fmt.Println(hello[0]) fmt.Println(primes[1:]) fmt.Println(primes[1:2]) }
Array in Go and how we sliced the array to get the value.
Map
package main import "fmt" type location struct { latitude, longitude float64 } func main() { offices := map[string]location{ "Apple": { 37.33199, -122.03089, }, "Google": { 37.42202, -122.08408, }, } fmt.Println(offices["Apple"]) fmt.Println("Google is at:", offices["Google"].latitude, offices["Google"].longitude) }
Map, key-value pairs, in Go.
For
package main import "fmt" func typical() { for i := 1; i <= 5; i++ { for j := 0; j < i; j++ { fmt.Print("*") } fmt.Print("\n") } } func while() { sum := 1 for sum < 1000 { sum += sum } fmt.Println(sum) } func main() { typical() while() }
Go only used the for
syntax for looping. Take a look at the code above about how we implement the while
loop with for
in Go.
If
package main import ( "fmt" ) func isEven(number int) { if number%2 == 0 { fmt.Println(number, "is even.") } else { fmt.Println(number, "is odd.") } } func main() { isEven(1) }
The for
and if
have no braces in Go.
Switch
package main import ( "fmt" "time" ) func noCondition() { t := time.Now() switch { case t.Hour() < 12: fmt.Println("Good morning!") case t.Hour() < 17: fmt.Println("Good afternoon.") default: fmt.Println("Good evening.") } } func typical(day string) { switch day { case "Monday": fmt.Println("Mathematics") case "Wednesday": fmt.Println("Computer Science") case "Friday": fmt.Println("Physics") default: fmt.Println("Off") } } func main() { typical("Today") noCondition() }
The break
is optional. The switch
can contain no condition. It could be a clean way to write long if-then-else chains.
Defer
package main import "fmt" func main() { defer fmt.Println("World!") fmt.Println("Hello...") for i := 1; i <= 3; i++ { defer fmt.Println(i) } }
A defer
statement defers the execution of a function until the surrounding function returns.
Conclusion
The reference for this article is from the official website of Go. You can practice more at https://tour.golang.org/list. You can get the source code at https://github.com/aristorinjuang/go-crash-course_02.