joplin-notes/joplin notion extension/Web Development/Go/Basics.md
2026-11-04 00:33:23 +05:30

5.8 KiB

Basics

datatypes

Spec term What it covers
Basic types (predeclared) bool, string, numeric types (int, uint, float, complex, byte, rune)
Composite types (via type literals) array, struct, pointer, function, interface, slice, map, channel

Variables

There are mainly 3 data types ie bool, Numeric (int and float32) and string.

There are 2 ways to declare a variable

  1. with var keyword var variablename type = value(with initial value) or var variablename type(with no initial value)
  2. with := sign variablename := value . data type is assigned with initial value type so there is no way to declare it without initial value. Also this method can be only used inside a function

eg

package main
import ("fmt")

func main() {
 var student1 string = "John" //type is string
 var student2 = "Jane" //type is inferred
 x := 2 //type is inferred

 fmt.Println(student1)
 fmt.Println(student2)
 fmt.Println(x)
}

for multiple values

var a, b, c, d int = 1, 3, 5, 7

or

 var (
     a int
     b int = 1
     c string = "hello"
   )

Similarly there are constants whose value cant be changed and is read-only it dont have that := thing and can be even defined without type

const (
  A int = 1
  B = 3.14
  C = "Hi!"
)

 

Output functions

It has Print, Println and Printf

func main() {
  var i string = "Hello"
  fmt.Printf("i has value: %v and type: %T\n", i, i)
}

%v and %T are formatting verbs

%v 	Prints the value in the default format
%#v 	Prints the value in Go-syntax format
%T 	Prints the type of the value
%% 	Prints the % sign
package main
import ("fmt")

func main() {
  var i = 15.5
  var txt = "Hello World!"

  fmt.Printf("%v\n", i)
  fmt.Printf("%#v\n", i)
  fmt.Printf("%v%%\n", i)
  fmt.Printf("%T\n", i)

  fmt.Printf("%v\n", txt)
  fmt.Printf("%#v\n", txt)
  fmt.Printf("%T\n", txt)
}

 

Data types

  1. Integers int, uint for signed and unsigned integers . Also int8, int16, ..
  2. Float
func main() {
  var x float64 = 1.7e+308
  fmt.Printf("Type: %T, value: %v", x, x)
}

 

Arrays

Syntax

var array_name = [length]datatype{values} // here length is defined

// or

var array_name = [...]datatype{values} // here length is inferred 

// or

array_name := [length]datatype{values} // here length is defined

// or

array_name := [...]datatype{values} // here length is inferred 

eg

func main() {
  var arr1 = [3]int{1,2,3}
  arr2 := [...]int{4,5,6,7,8}
  // or
  // declaring a array  with no initialization
	var a [5]int

  fmt.Println(arr1)
  fmt.Println(arr2)
}

in case of integer array, if all the elements are not initialized then those remaining ones will be filled with 0.

To initialize specific elements

func main() {
  arr1 := [5]int{1:10,2:40}

  fmt.Println(arr1)
	
	// to get length of array
	fmt.Println(len(arr1))
}

Output [0 10 40 0 0]  

and to find element position in array index := slices.Index(myArray[:], target) and for array of structs

index := slices.IndexFunc(users[:], func(u User) bool {
		return u.ID == targetID
	})

Slices

Slices are like arrays and unlike arrays its size can grow or shrink. It has length and capacity thing.

Syntax

slice_name := []datatype{values} 

and

slice_name := make([]type, length, capacity)

example

func main() {
  myslice1 := []int{}
  fmt.Println(len(myslice1))
  fmt.Println(cap(myslice1))
  fmt.Println(myslice1)

  myslice2 := []string{"Go", "Slices", "Are", "Powerful"}
  fmt.Println(len(myslice2))
  fmt.Println(cap(myslice2))
  fmt.Println(myslice2)
	
	myslice3 := make([]int, 5, 10)
}

to change or access elements it is same as arrays. To append elemnts use append function slice_name = append(slice_name, element1, element2, ...) or slice3 = append(slice1, slice2...)  

For changing the length of array


func main() {
  arr1 := [6]int{9, 10, 11, 12, 13, 14} // An array
  myslice1 := arr1[1:5] // Slice array
  fmt.Printf("myslice1 = %v\n", myslice1)
  fmt.Printf("length = %d\n", len(myslice1))
  fmt.Printf("capacity = %d\n", cap(myslice1))

  myslice1 = arr1[1:3] // Change length by re-slicing the array
  fmt.Printf("myslice1 = %v\n", myslice1)
  fmt.Printf("length = %d\n", len(myslice1))
  fmt.Printf("capacity = %d\n", cap(myslice1))

  myslice1 = append(myslice1, 20, 21, 22, 23) // Change length by appending items
  fmt.Printf("myslice1 = %v\n", myslice1)
  fmt.Printf("length = %d\n", len(myslice1))
  fmt.Printf("capacity = %d\n", cap(myslice1))
	
		
	neededNumbers := arr3[:len(arr3)-4]
	numberCopy := make([]int, len(neededNumbers))
	copy(numberCopy, neededNumbers)

	// or
	// neededNumbers... is like ...arr in js
	numberCopy = append([]int(nil), neededNumbers...)
	
	

	fmt.Printf("numberCopy = %v\n", numberCopy)
	fmt.Printf("length = %d\n", len(numberCopy))
	fmt.Printf("capacity = %d\n", cap(numberCopy))
	fmt.Println("for neededNumbers:")
	fmt.Printf("capacity = %d\n", cap(neededNumbers))
}

Capacity will increase too automatically  

Memory Efficiency When copying elements from array, by default go will load all elements to memory so in order to copy few elements from large array it is better to use copy function.

 

runes character array of string but containing ascii code instead of characters

import "unicode/utf8"

str:= "AB"
runes:= []rune(str) // [65 66]

buf := make([]byte, utf8.RuneLen(runes[0]))
utf8.EncodeRune(buf, runes[0]) // [65]

fmt.Println("string form: ", string(runes)) // AB

byteSlice := []byte(string(runes)) // [65 66]
as character array 
fmt.Printf("%c\n", runes) // [A B]


// to string slice
sli := strings.Split(str, "") // [A B] -> not rune slice but string slice
	
slistr := strings.Join(sli, "") // AB
	


byteslice is of utf8 so takes mostly text but rune slice covers much as its int32