Go Programming Languages - Fundamentals
Table of Contents
- Overview
- Environment Variable
- Basic Command
- Go Fundamentals
Overview
The go programming language has the features in C, Java and Python. Go programming language is a grammar-sensitive language, meaning that the language attached great importance on grammar. Go supports gabbage collection. Go does not support inheritance and overloading, but supports interface. Go supports concurrency. Go does not support casting. Go does not support assert (third-party packages available), Go does not support static variable.
Environment Variable
GOROOT
: the place where you install the GoGOPATH
: the place where you store the source code- src: source code
- pkg: dependent package
- 国内用户建议设置goproxy: export GOPROXY=https://goproxy.cn
Basic Command
command | content |
---|---|
bug | start a bug report |
build | compile packages and dependencies |
clean | remove object files and cached files |
doc | show documentation for package or symbol |
env | print Go environment information |
fix | update packages to use new APIs |
fmt | gofmt (reformat) package sources |
generate | generate Go files by processing source |
get | add dependencies to current module and install them |
install | compile and install packages and dependencies |
list | list packages or modules |
mod | module maintenance |
run | compile and run Go program |
test | test packages (go test will scan for all files ending with *_test.go, so put test and src files together) |
tool | run specified go tool |
version | print Go version |
vet | report likely mistakes in packages |
Go Fundamentals
Hello World
The first and foremost thing for a programming language is to
understand the basic hello_world.go 1
2
3
4
5
6
7package main
import "fmt"
func main() {
fmt.Println("hello world")
}
package main
indicates where the package is in, this is the entry point for go programs- There is only one main function in one package
import "fmt"
indicates importing a packagefunc main
like many other languages, the main function- However, the main does not need input arguments - like Python
- uses
os.Args
to obtain arguments
Input from stdin
1 | //take input like scanf in C |
Variable
Initialization
There are two ways to define a variable
Implicitly initialize
1
2var a int
// equivalent to var a int = 0Define initial value but without stating the variable type
1
var a = 1
Define initial value plus variable type
1
var a int = 1
(new) convenient way without var
1
2a := 1
// equivalent to var a := 1使用
var()
集中定义变量1
2
3
4
5
6
7
8
9var (
a int
b string
c []float32
d func() bool
e struct {
x int
}
)编译器智能决定变量
1
2// only can be used in a function
var a, b, i, s1, s2 = true, false, 3, "Hello", "World"
Explicit conversion (强制类型转换)
- Go中,类型转换是强制的(没有隐式转换)
1
2
3
4
5
6var a, b int = 3, 4
// wrong, math.Sqrt returns float64
// also, a * a + b * b is int, not float64
var c int = math.Sqrt(a * a + b * b)
// correct, must explicitly convert
var c int = int(math.Sqrt(float64(a*a + b*b)))
Type
Basic Types
bool
string
int
,int8
,int16
,int32
,int64
,uint
,uint8
,uint16
,uint32
,uint64
byte
// alias foruint8
rune
// char in java, alias forint32
- official:rune is an alias for int32 and is equivalent to int32 in all ways. It is used, by convention, to distinguish character values from integer values.
float32
,float64
complex64
,complex128
Constant
Initialization
Full version
1
const a int = 1
Without stating the type
In Go programming language, the initialization cannot be like the following:1
const a = 1
1
2const a int // not legal
a = 1 // not legal
Enum (No enum explicitly in Go)
1 | const ( |
For simplicity, we can use iota
keyword for auto
increment 1
2
3
4
5
6const (
cpp = iota
java
python
golang
)
For more advanced usage: 1
2
3
4
5
6
7
8
9// e.g., we want to create b, kb, mb, gb, tb, pb...
const (
b = 1 << (10 * iota)
kb
mb
gb
tb
pb
)
Condition Statement
For loop
1 | package main |
here j:=1
is the alias for var int j = 1
In
java, the type can be written in the for loop condition 1
2
3
4for (int i=0; i<10; i++) {
// statement here
}1
2
3
4var j = 1
for j=1; j<10; j++ {
// statement here
}**while**
statement,
meaning that if you want to do while statement, the way to do that is to
limit the condition to just one: 1
2
3
4
5var j = 1
for j < 10 {
//statement here
j = j + 1
}1
2
3
4
5
6
7
8
9
10var j = 1
// infinite loop
for {
//statement here
j = j + 1
if j >= 10 {
break
}
}
For also allowed for three ways that substitute the
while
ignore initial state
1
2
3
4
5
6
7func convertToBin(v int) string {
result := ""
for ; v > 0 ; v /= 2 {
result = strconv.Itoa(v % 2) + result
}
return result
}ignore initial and final state
1
2
3for scanner.Scan() {
fmt.Println(scanner.Text())
}ignore initial and final state, and update condition
1
2
3
4// equals to while (true)
for {
fmt.Println("abc")
}
If/else
Similar to most of the language, with a few exceptions:
- Can exclude
()
, but cannot exclude{}
, the left bracket{
must be on the same line withif
statement - Go doesn't have Ternary Operator ( x < 0 ? A : B )
1 | package main |
Another way to write this would be:
1 | package main |
Switch
Switch statements in go propgramming language doesn't require break;
they will break by default, fallthrough keyword used to go to NEXT
statement even if condition doesn't match, fallthrough
is
like a continue so statement that after it will also executed. however a
workaround is to use labels
and goto
1
2
3
4
5
6
7
8
9switch var1 {
case var1:
case var2:
fallthrough
case var3:
f()
default:
...
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16func eval(a, b int, op string) {
var result int
switch op {
case "+":
result = a + b
case "-":
result = a - b
case "*":
result = a * b
case "/":
result = a / b
default:
panic("unsupported operator:" + op)
}
return result
}
Note:
Switch will automatically "break" (we do not need to write break)
fallthrough
= continue running the following code without breaking
Array
Initialzation
ways of declaring initialization 1
2
3
4
5
6
7
8// first one
var a [3] int
var balance [10] float32
arr2 := [3]int{1, 3, 5}
arr3 := [...]int{2, 4, 6, 8, 10}
// two-dimension
var x [3][2] int
iterate over array
1 | // first method |
Slices
Slices are of dynamic size 1
2
3
4
5
6
7
8
9letters := []string{"a", "b", "c", "d"}
/* using make -> make([]T, len, cap) */
var s []byte
s = make([]byte, 5, 5)
//OR
s := make([]byte, 5)
// both equiavlent to: s == []byte{0, 0, 0, 0, 0}
- 左开右闭
- A slice does not store any data, it just describes a section of an underlying array. Changing the elements of a slice modifies the corresponding elements of its underlying array. Other slices that share the same underlying array will see those changes.
- Slicing a slice changes pointers of the underlying array, so it is as efficient as manipulating array indices, size and capacity of the new slice are changed too.
- Example usage:
1
2
3
4
5
6
7
8names := [4]string{"John","Paul","George","Ringo",}
fmt.Println(names) //[John Paul George Ringo]
a := names[0:2]
b := names[1:3]
fmt.Println(a, b) //[John Paul] [Paul George]
b[0] = "XXX"
fmt.Println(a, b) //[John XXX] [XXX George]
fmt.Println(names) //[John XXX George Ringo]
Difference between slice and array
1 | //This is an array literal: |
Iterating over slice
1 | for i, v := range arr { //do stuff } |
Map
Map format: map[k]v
1 | m := map[string]string { |
Create a map
1 | // m2 == empty map |
Traversing the map (using range)
1 | for k, v := range m { |
Get Element
Unlike Python when accessing non-exist key, it will pop exceptions,
Go will not, and it will return two values on accessing the value
through keys, 1) the value itself, and 2) a bool of whether the element
exists 1
2
3
4
5
6
7
8// ok will be whether the key exists
courseName, ok := m1["course"]
if courseName, ok := m1["course"]; ok {
fmt.Println("causeName")
} else {
fmt.Println("key does not exist")
}
Delete Element
The delete() function is a direct and effective way to eliminate a
key−value pair from a map. By specifying the key to delete, you can
promptly remove the corresponding data from the map. 1
2
3// delete(mapName, key)
name, ok := m["name"]
delete(m, "name")
Map's Key
- Map uses hashmap as its data structure, so other than slice, map, function, other type can be used as keys.
- Sturct data without slice, map and function can also be the key
Functions in Go
Typical Function
1 | // return void |
Multiple Returns
1 | func swap(x, y string) (string, string) { |
Named Returns
You can declare return variables and name them at the beginning, they
are returned in the end. 1
2
3
4
5
6
7
8//Returns x,y at the end.
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
// by default, it returns x and y
return
//return a,b <- u can override default return of x,y.
}
Variadic Functions
The rightmost argument can be a list of variable size
(slice) of data. ...
three dots means you are
passing a variable size of data 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18func average(x int, values ...int) float64 {
//print values
fmt.Println("Single argument value: ", x)
fmt.Println("Variable argument values: ", values)
//calculate average
total := 0
for _, value := range values {
total += value
}
return float64(total) / float64(len(values))
}
func main() {
avg := average(10,20,30,40,50)
println("Average:", avg)
}
Defer Keyword
Defer
used before a functions executes the function at
the end of the scope of it.
- usually used to close opened files/buffers so you open the file and closes it using defer in the next line to keep things clean.
- they're executed as a stack.
1
2
3
4
5
6fmt.Println("One")
defer fmt.Println("Four")
defer fmt.Println("Three")
fmt.Println("Two")
//Prints One Two Three Four
Type Function and Returning Functions
- Functions can be assigned to variables
func0 := func() int {x++; return x}
- Functions that are returned from another functions has its own scope
per returned function
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21package main
func incrementGlobalX() int {
x++
return x
}
func wrapper() func() int {
x := 0
return func() int {
x++
return x
}
}
func main() {
fn := wrapper()
fmt.Print(wrapper())
fmt.Print(wrapper())
// print 12
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36package main
var x = 0
func main() {
//local x
x := 0
func0 := func() int {x++; return x}
func1 := incrementGlobalX //without ()
func2 := wrapper()
func3 := wrapper()
println(func0(), " : func0 (local x)")
println(func1(), " : func1 (global x)")
println(func2(), " : func2 (per func scope x1)")
println(func3(), " : func3 (per func scope x2)")
println("Second Increment")
println(func0(), " : func0 (local x)")
println(func1(), " : func1 (global x)")
println(func2(), " : func2 (per func scope x1)")
println(func3(), " : func3 (per func scope x2)")
}
func incrementGlobalX() int {
x++
return x
}
func wrapper() func() int {
x := 0
return func() int {
x++
return x
}
}
Receiver
Receiver is the way you create a method for a specific type/struct
1
2
3
4
5
6
7
8
9
10
11
12type rect struct {
width, height int
}
// (r *rect) is called rceiver
func (r *rect) area() int {
return r.width * r.height
}
r := rect{2,3}
areaX := r.area()
fmt.Println(areaX)
Pointers
Similar to C/C++ 1
2
3
4
5
6
7
8
9var value int = 1000
var pointer *int = &value
println(value) //1000
println(pointer) //0xfffffffff
println(*pointer) //1000
(*pointer)++ //1001
*pointer = *pointer + 10 //1011
println(*pointer) //1011
println(*pointer + *pointer) //1011 + 1011 = 2022
Difference?
- Pointer cannot do arithmetic calculation: you can change what pointer points to, but you cannot change the pointer itself
Pass by value & Pass by reference
- Every thing is passed by value except arrays, slices, maps and channels which some calls reference types, these types are passed by reference ( they internally have pointers, so no copying of the actual data happens when passing them) .
- Unlike C, where the address of a local variable will be recollected after the function returns, it's perfectly OK to return the address of a local variable (like Java); the storage associated with the variable survives after the function returns.
Reference
- https://github.com/sherifabdlnaby/Golang-study-notes
- Coursera - Functions, Methods, and Interfaces in Go, University of California, Irvine.
- 慕课网 Google资深工程师深度讲解Go语言 由浅入深掌握Go语言
Go Programming Languages - Fundamentals
https://jerry20000730.github.io/wiki/程序语言/Go/Go_fundamentals/