Basic Types
bool string int (8, 16, 32, 64) uint (8, 16, 32, 64), uintptr - pointer byte (uint8) rune (uint32) like a char float (32, 64) complex (64, 128)
Other Types
Array Slice Struct Pointer Function Interface Map Channel
Variable Declaration
var foo string
foo = “Hello World”
var bar = “Hello World” => same as above interprets the type automatically
baz := “Hello World” => no need to type in var
Pointers
ptr -> var
string pointer cannot point to int pointer
pointer holds memory address
if we pass a pointer to a function then if the value changes outside of function then it also effects the value inside of the function.
message := “Hello World….”
var greeting *string = &message
Note: *string is required to store pointer value
&message => gets back address of message - this has to be stored inside a string pointer
fmt.Println(greeting, *greeting)
output => 0x123423, Hello World….
User Defined Types
type Customer struct {
name string
age int
}
func main(){
c1 = Customer{}
c1.name = "Foo"
c1.age = 10c2 = Customer {name: “Bar”, age: 20}
c3 = Customer {“Bar”, 20}
}
Notes:
Constants
const {
PI = 3.14 => float const
Language = "Go" => string const
}
const {
A = iota
B = iota
C = iota
}
fmt.Println(A, B, C)
0, 1, 2
const {
A = iota
B
C
}fmt.Println(A, B, C)
0, 1, 2
Functions
func Greet (s Salutation){
fmt.Println(CreateMessage(s.name, s.age))
}
func CreateMessage(name string, age int) string {
return "hello " + name + ", your age is " + age
}Functions with multiple return types
func Greet (s Salutation){
m1, m2 = CreateMessage(s.name, s.age)
fmt.Println(m1, m2)
}
func CreateMessage (s Salutation) (string, string){
return "foo", "bar"
}===
s = Salutation {“foo”, 10}
Greet(s)
output
foo, bar
if you do not use a variable its an ERROR, so just use _ if you do not want a variable
i.e. _, m2 = CreateMessage(s.name, s.age)
Functions with names multiple return types
func CreateMessage(s Salutation) (message string, alternate string){
message = "foo"
alternate = "bar"
return
}Variadic Functions
func foo(name string, options ...string){
fmt.Println(name, options[0], options[1])
}foo(“hello world”, “foo”, “bar”)
Function Types
func foo (name string, myfun string(int) (string)){
"Hello " + name + ", drinking age? " + myfun(10)
}func DrinkingEligible (age int) (string){
if (age > 18){
return "Yes"
}
else{
return "No"
}
}==
foo(“hello “, DrinkingEligible)
Func Type 2
type DrikingEligibilityCalculator string(int) (string)
func foo (name string, cal DrinkingEligibilityCalculator){
"Hello " + name + ", drinking age? " + cal(10)
}func DrinkingEligibilityUS (age int) (string){
if (age > 21){
return "Yes"
}
else{
return "No"
}
}func DrinkingEligibilityUK (age int) (string){
if (age > 18){
return "Yes"
}
else{
return "No"
}
}
==
foo("hello ", DrinkingEligibleUS)
foo("hello ", DrinkingEligibleUK)If statements
if age := 100 alive {
print("still alive at ", age)
}
else{
print("not alive at ", age)
}age is defined in scope of the if statement.
Switch statement
switch name{
case "bob":
print("Hello Bob")
case "sally":
print("hello sally")
default:
print("No name")
}
no switching param needed, it will switch on bool
switch {
case name == "bob":
print("Hello Bob")
case name == "sally":
print("hello sally")
default:
print("No name")
}Loops
only have one type of loop i.e. FOR
for i := 0; i < 10; i++{
}
// similar to while loop
i := 0
for i < 10 {
i ++
}for {
break;
}
Ranges
slice := [] foo {
“one”, “two”, “three”
}
for index, val := range slice {
print (“index: “ + index + “, value: “ + val)
}
Maps
var foo map [string] string {}
foo = make(map [string] string)
initialization #1
foo[“bar”] = “aaaa”
foo[“baz”] = “bbbb”
initialization #2
var foo map [string] string {
"bar": "aaaa",
"baz": "bbbb"
}to get values
foo[“bar”]
Operations == insert update => foo["baz"] = "kkkkk" delete => delete(foo, "baz")
Slices
long version
var foo [] int
foo = make([] int, 5, 10) => make a a slice of integers with initial length of 5 and capacity of 10
foo := [] int {1, 2, 3}
bar := [] baz {
{id: 1, name: “”}, {id: 2, name: “”}
}
slice of baz struct
slicing operations == foo[1:2] => 2 foo[0:2] => 1, 2 foo[0:] => 1, 2, 3
append(foo, 100)
append(foo, foo…) => append two slices
Methods on Struct
functions v/s methods (operate on structs)
type Customer struct {
Id string
Name string
}
type Customers [] Customer
func (customers Customers) SayHello(){
for _, c := range customers {
print(c.Id, c.Name)
}
}usage
==
goodCustomers := Customers {
{1, "Alice"}, {2, "Bob"}, {3, "Cathy"}
}goodCustomers.SayHello()
Methods
type Customer struct {
Id string
Name string
}
func (customer *Customer) rename (newName sting){
customer.name = newName
}here we have a pointer to the object, so it will change the underlying struct
john = Customer {1, “John”}
john.rename(“bob”)
Concurrency
o/p
func sayHello(arg){
print("Hello world...")
}go sayHello(“Concurrent”) ====> runs on its own thread
sayHello(“Normal”)
time.Sleep(100 * time.Millisecond)
Hello World Normal
Hello World Concurrent