This repository is a comprehensive collection of notes on Java and Go programming languages, designed for both beginners and experienced learners. It offers a variety of resources including code snippets, tips, and tricks to help users enhance their knowledge of these languages.
These are the basic types in Go
The int, uint and uintptr are 32 bits in 32 bits machines and 64 in 64 bits machines
If an integer is needed, int should be used unless there is a special need
To convert from one type to another, the statement is T(v) where T is the type and v the value
var i int = 42
var f float64 = float64(i)
i := 42
f := float64(i)
The var statement declares a list of variables
var var1, var2, var3 type
var c, python, java bool
var i int
If a variable is declared without an explicit initial value, it is given it’s zero value
0 for numeric typesfalse for boolean type"" (empty string) for string typeDeclarations can include initializers, one per variable
var i, j int = 1, 2
If there is an initializer present, the type can be ommited and the variable takes the type of the initializer
var c, python, java = true, false, "no!"
Only inside functions the := operator can be used instead of a var statement, the type is implicit
They are declared like variables but with the const keyword and cannot be declared with the := operator
const Pi = 3.14
Untyped constants take the type needed by the context
Can take 0 or more parameters
Type comes after variable name and return value comes after function parameters
func add(x int, y int) int {
return x + y
}
If many parameters share the same type, the type can be ommited except for the last one
func add(x, y int) int {
return x + y
}
Can return 0 or more results, sepparated by a comma (“,”)
func swap(x, y string) (string, string) {
return y, x
}
Can use named return values, used as variables declared at the top of the function. Those values are returned with a “naked” return (this should be used only in short functions because it harms readability)
func split(sum int) (x, y int){
x = sum * 4 / 9
y = sum - x
return
}
Everything inside the main function is run
func main(){
...
}
There are 2 ways of importing stuff
Multiple statements:
import "fmt"
import "math"
Factored statement:
import (
"fmt"
"math"
)
Any function beginning with capital letter is exported, and accessable with the dot (“.”) operator
Programs start running in package main
package main
Package name is the same as the last element of the import path
The only looping statement is the for
The for has the init statement(optional), condition statement and the post statement(optional), all separated by ;
sum := 0
for i := 0; i < 10; i++ {
sum += 1
}
The “while” is a for without the init and post statements
sum := 1
for sum < 10 {
sum += sum
}
Infinite loop compressed
for {
...
}
The expression between the “if” and the braces (“{}”) is evaluated
func do(x int) {
if x < 5 {
return 1
}
return 0
}
Variables can be declared inside the scope of the if statement and will last until the end of the if.
func do(x int) {
if y := x + 4; y > 10 {
return y
}
return 0
}
Variables declared inside the scope of an if can be used in an else
func do(x int) {
if y := x + 4; y > 10 {
return y
} else {
return y - 10
}
}
Switches only run the selected case, and can use scope declarations like an if
func exaple(x string) {
switch v := x + "_"; v {
case "hi_":
...
case "bye_":
...
default:
...
}
}
break statements are not needed, they are provided automatically by Go
Cases are evaluated from top to bottom, and in a lazy way, it stops when it finds a match
If the switch has no condition, it is the same as switch true
func whatTime(t int) string {
switch {
case t < 12:
return "am"
case t < 24:
return "pm"
default:
return "wtf"
}
}
The defer statement postpones the execution of a function until the enclosing function returns
import "fmt"
func main() {
defer fmt.Println("World")
fmt.Println("Hello")
}
The function above prints “Hello World”
Multiple defered function calls are pushed onto a stack, and when the enclosing funcion ends, it calls them in a LIFO order.
import "fmt"
func main() {
fmt.Println("start")
for i := 0; i < 10; i++ {
defer fmt.Println(i)
}
fmt.Println("end")
}
The function above prints “start end 9 8 7 6 5 4 3 2 1 0”
Go has pointers.
It’s zero value is nil
There is no pointer arithmetic
How to declare a pointer:
var p *int
To generate a pointer to a variable you use the & operator:
i := 43
p = &i
To dereference the value of the pointer you use the * operator:
fmt.Println(*p)
*p = 21
Collection of fields
type Point struct {
x int
y int
}
There are multiple ways to create an instance of a struct
Using the Name: syntax (order of fields is irrelevant)
v = Vertex{x: 1} // y:0 is implicit
Using all implicit values
v = Vertex{} // y:0 and x:0 is implicit
Using all explicit values
v = Vertex{1, 2}
Fields are accessed via the dot operator (.)
v = Point{1, 2}
v.x = 4
Fields can also be accessed via pointers to structs, there is no need to dereference the pointer
v := Point{1, 2}
p := &v
p.x = 1e9
Arrays cannot be resized and use zero-based notation
They are declared like this
var a [10]int
Or like this in an explicit declaration of elements
a := [6]int{1,2,3,4,5,6}
These are dynamically-sized flexible views into arrays
It’s zero value is nil
They are like references to an array, any modification to the slice will impact the array and other slices referencing that array part
They have properties:
len(slice)cap(slice)It needs an upper and lower bound to be created (lower bound included and upper bound excluded)
a[low : high]
These can be ommited in order to use default values, the default for low is 0 and the default for high is the array length
They are declared like this
a := [6]int{1,2,3,4,5,6}
var s []int = a[1:4]
s = a[:4]
s = a[3:]
s = a[:]
Slices can also be declared in a literal way(note the lack of length between the [])
b := []bool{false, true, false}
This creates the array then it creates the slice from it
Slices can also be created using make, it allocates a zeroed array and returns a reference to that array using make(array, length, capacity) or make(array, length)
a := make([]int, 5)
b := make([]int, 0, 5)
There is a built in funcion to append to a slice
func append(s []T, vs ...T) []T
The result is the give slice with the extra elements
var s []int
s = append(s, 4)
s = append(s, 3)
There is a range form of the for loop
Two values are returned in each iteration, the index and a copy of the element
for i, v := range elems {
// do smth
}
The index or the value can be skipped.
// Skipping the index
for _, value := range elems{
// do smth
}
// Skipping the value
for i, _ := range elems{
// do smth
}
for i := range elems{
// do smth
}
It maps keys to values
It’s zero value si nil, it has no keys and keys cannot be added
It can be created using make
type Point struct {
x, y float64
}
var m map[string]Point
func main() {
m = make(map[string]Point)
m["Origin"] = Point{0.0, 0.0}
}
It can be created in a literal way
var m map[string]Point{
"Origin": Point{
0.0, 0.0
},
"One-One": Point{
1.0, 1.0
}
}
If the top-level type is a type name, it can be omited
var m map[string]Point{
"Origin": {
0.0, 0.0
},
"One-One": {
1.0, 1.0
}
}
To insert/update an element
m[key] = elem
To retrieve an element
elem = m[key]
To delete an elem
delete(m, key)
To query if a jey is present
elem, ok = m[key]
// If key is in m, ok is true. It is false otherwise
Functions can be passed as values and returned as return values
The type for a function is func(params) returnValue
func compute(fn func(float64, float64) float64){
return fn(3, 4)
}
func main() {
hypot := func(x, y float64) float64 {
return math.Sqrt(x*x + y*y)
}
fmt.Println(compute(hypot))
}
Functions can be closures, it means it can reference variables outside its body and be bound by that value
Go does not have classes
Methods can be defined, and have a receiver which is the object that receives the call to the methods
You need an instance of the receiver to be able to call the method
Methods are functions with receiver arguments
Many objects can be receivers:
// Here Abs() is a method that has a Point as a receiver func (p Point) Abs() float64 { return math.Sqrt(p.xp.x + p.yp.y) }
func main(){ myPoint := Point{1,2} fmt.Println(myPoint.Abs()) }
- Non-struct types
type MyFloat float64
func (mf MyFloat) Abs() float64 { if mf < 0 { return float64(-mf) } return float64(mf) }
func main(){ mf := MyFloat{1.432} fmt.Println(mf.Abs()) }
- Pointers
type Point struct { x, y float64 }
// Here Abs() is a method that has a Point as a receiver func (p Point) Abs() float64 { return math.Sqrt(p.xp.x + p.y*p.y) }
func main(){ myPoint := Point{1,2} fmt.Println(myPoint.Abs()) }
If the receiver is not a pointer, values held by the receiver cannot be modified because the program is working with a copy. Pointers need to be used if the values contained in the receiver want to be changed
## Interfaces
Interfaces are defined as a set of method signatures
type Abser interface { Abs() float64 }
A value of the interface type can hold any object that implements the interface
They are **implicitly** implemented, there is no way to declare that a receiver implements an interface
The receiver can be `nil` when calling the function interface, but this does not generate a null pointer exception
func (t *T) M() {
if t == nil {
fmt.Println(“
### Empty Interfaces
Empty interfaces can hold values of any type
func main(){ var i interface{} i = 42 i = “hello” }
Useful when the type is not known
## Type Assertions
The type of a variable can be asserted in this way (`T` is the type being asserted)
t := i.(T)
If the variable `i` is not of type `T`, it will panic
There is an alternate way, in order to assert this
t, ok := i.(T)
Where `ok` will be `true` if it is of type `T` or `false` otherwise, and `t` will have the value of `i` or the zero value otherwise
### Type Switches
The value of a type assertion can be used in switches in this way
func do(i interface{}) { switch v := i.(type) { case int: fmt.Printf(“Twice %v is %v\n”, v, v*2) case string: fmt.Printf(“%q is %v bytes long\n”, v, len(v)) default: fmt.Printf(“I don’t know about type %T!\n”, v) } }
func main() { do(21) do(“hello”) do(true) }
Note the `v := i.(type)`
## Errors
Functions return error values along with the returned values, if there is an error, it will return something different than `nil` in the error variable
i, err := strconv.Atoi(“42”) if err != nil { fmt.Printf(“couldn’t convert number: %v\n”, err) return } fmt.Println(“Converted integer:”, i)
## Readers
The IO package contains `readers`, which are the read end of streams of data
All readers contain a method called `Read`
func (T) Read(b []byte) (n int, err error)
Where `n` is the amount of bytes read and `err` is the return value of the operation
If there is no more data to read, it will return `io.EOF` in `err`
# Go Tour Exercise Solutions
## Exercise: Slices
[Problem URL](https://tour.golang.org/moretypes/18)
Problem:
Implement Pic. It should return a slice of length dy, each element of which is a slice of dx 8-bit unsigned integers. When you run the program, it will display your picture, interpreting the integers as grayscale (well, bluescale) values.
The choice of image is up to you. Interesting functions include (x+y)/2, x*y, and x^y.
(You need to use a loop to allocate each []uint8 inside the [][]uint8.)
(Use uint8(intValue) to convert between types.)
Solution:
package main
import “golang.org/x/tour/pic”
func Pic(dx, dy int) [][]uint8 { s := make([][]uint8, dy) for i := 0; i < dy; i++ { s[i] = make([]uint8, dx) for j := 0; j < dx; j++ { s[i][j] = transform(i, j) } } return s }
func transform(x, y int) uint8 { var val uint8 = uint8(x^y) return val }
func main() { pic.Show(Pic) }
## Exercise: Maps
[Problem URL](https://tour.golang.org/moretypes/23)
Problem:
Implement WordCount. It should return a map of the counts of each “word” in the string s. The wc.Test function runs a test suite against the provided function and prints success or failure.
You might find strings.Fields helpful.
Solution:
package main
import ( “golang.org/x/tour/wc” “strings” )
func WordCount(s string) map[string]int { m := make(map[string]int) words := strings.Fields(s) for i := 0; i < len(words); i++ { elem := m[words[i]] m[words[i]] = elem + 1 } return m }
func main() { wc.Test(WordCount) }
## Exercise: Fibonacci closure
[Problem URL](https://tour.golang.org/moretypes/26)
Problem:
Let's have some fun with functions.
Implement a fibonacci function that returns a function (a closure) that returns successive fibonacci numbers (0, 1, 1, 2, 3, 5, ...).
Solution:
package main
import “fmt”
// fibonacci is a function that returns // a function that returns an int. func fibonacci() func() int { prevToPrev, prev := 0, 1 return func() int { toReturn := prevToPrev prevToPrev, prev = prev, prev + prevToPrev return toReturn } }
func main() { f := fibonacci() for i := 0; i < 10; i++ { fmt.Println(f()) } }
## Exercise: Stringers
[Problem URL](https://tour.golang.org/methods/18)
Problem:
Make the IPAddr type implement fmt.Stringer to print the address as a dotted quad.
For instance, IPAddr{1, 2, 3, 4} should print as "1.2.3.4".
Solution:
package main
import “fmt”
type IPAddr [4]byte
// TODO: Add a “String() string” method to IPAddr.
func (ip IPAddr) String() string { return fmt.Sprintf(“%v.%v.%v.%v”, ip[0], ip[1], ip[2], ip[3]) }
func main() { hosts := map[string]IPAddr{ “loopback”: {127, 0, 0, 1}, “googleDNS”: {8, 8, 8, 8}, } for name, ip := range hosts { fmt.Printf(“%v: %v\n”, name, ip) } }
## Exercise: Readers
[Problem URL](https://tour.golang.org/methods/22)
Problem:
Implement a Reader type that emits an infinite stream of the ASCII character 'A'.
Solution:
package main
import “golang.org/x/tour/reader”
type MyReader struct{}
// TODO: Add a Read([]byte) (int, error) method to MyReader.
func (reader MyReader) Read(s []byte) (int, error){ s = s[:cap(s)] for i := range s { s[i] = ‘A’ } return cap(s), nil }
func main() { reader.Validate(MyReader{}) }
## Exercise: rot13Reader
[Problem URL](https://tour.golang.org/methods/23)
Problem:
A common pattern is an io.Reader that wraps another io.Reader, modifying the stream in some way.
For example, the gzip.NewReader function takes an io.Reader (a stream of compressed data) and returns a *gzip.Reader that also implements io.Reader (a stream of the decompressed data).
Implement a rot13Reader that implements io.Reader and reads from an io.Reader, modifying the stream by applying the rot13 substitution cipher to all alphabetical characters.
The rot13Reader type is provided for you. Make it an io.Reader by implementing its Read method.
Solution:
package main
import ( “io” “os” “strings” )
type rot13Reader struct { r io.Reader }
func rot13byte(sb byte) byte { s := rune(sb) if s >= ‘a’ && s <= ‘m’ || s >= ‘A’ && s <= ‘M’ { sb += 13 } if s >= ‘n’ && s <= ‘z’ || s >= ‘N’ && s <= ‘Z’ { sb -= 13 }
return sb } func (rot13 rot13Reader) Read(data []byte) (readed int, err error) {
readed, err = rot13.r.Read(data)
for i := 0; i < readed; i++ {
data[i] = rot13byte(data[i])
}
return }
func main() { s := strings.NewReader(“Lbh penpxrq gur pbqr!”) r := rot13Reader{s} io.Copy(os.Stdout, &r) }
## Exercise: Images
[Problem URL](https://tour.golang.org/methods/25)
Problem:
Remember the picture generator you wrote earlier? Let's write another one, but this time it will return an implementation of image.Image instead of a slice of data.
Define your own Image type, implement the necessary methods, and call pic.ShowImage.
Bounds should return a image.Rectangle, like image.Rect(0, 0, w, h).
ColorModel should return color.RGBAModel.
At should return a color; the value v in the last picture generator corresponds to color.RGBA{v, v, 255, 255} in this one.
Solution:
package main
import ( “golang.org/x/tour/pic” “image” “image/color” )
type Image struct { rows, cols int }
func (m *Image) Bounds() image.Rectangle { return image.Rect(0, 0, m.rows, m.cols) }
func (m *Image) ColorModel() color.Model { return color.RGBAModel }
func (m *Image) At(x, y int) color.Color { v := uint8(x ^ y) return color.RGBA{v, v, 255, 255} }
func main() { m := Image{64, 64} pic.ShowImage(&m) } ```