Composite types and interface types in Go
Arrays
An array is a fixed-length collection of elements of the same type.
Slices
Slices are more flexible than arrays because they do not have a fixed size.
Structs
A struct is a user-defined type that groups multiple fields.
Maps
A map is a collection of key-value pairs.
Channels
Channels in Go are a powerful feature used for communication between goroutines, enabling concurrent programming. Channels allow goroutines to communicate safely. Channels are a way for goroutines to communicate with each other and synchronize their execution. They can be thought of as pipes through which data can be sent and received.
- Channels can be created using a make() function.
- Data can be sent and received through channel using <- operators
- Channels can also be buffered by specifying the capacity
- Channels can be closed using a close() function.
- select statements allows a goroutine to wait on multiple channels.
Interface Types
Interfaces define a set of method signatures that a type must implement. A “set of method signatures” refers to a collection of function definitions (without implementations) that an interface requires. These method signatures specify:
- Method name
- Input parameters (if any)
- Return type(s) (if any)
Interface datatype usually consists of a set of functions declarations which are called a set of method signatures.
Below is code segment that defines various types of variables:
Example: Declaring and Using Maps
package main
import (
"fmt"
"reflect"
"runtime"
)
func main() {
//Below line of code is to get the file name and line number
// It is very much useful in debugging or unit testing your code
_, file, line, ok := runtime.Caller(0)
if ok {
fmt.Printf("Arrays: File: %s, Line: %d\n", file, line)
}
// Array variables
var numbers [5]int // Declaring an integer array of length 5
numbers[0] = 10 // Assigning a value
fmt.Println(numbers) // Output: [10 0 0 0 0]
// Shorter way using an array literal
fruits := [3]string{"Apple", "Banana", "Cherry"}
fmt.Println(fruits) // Output: [Apple Banana Cherry]
// reflect.TypeOf is used used to get the data type of a variable
fmt.Println(reflect.TypeOf(numbers), reflect.TypeOf(fruits))
// Arrays and Slices
_, file, line, ok = runtime.Caller(0)
if ok {
fmt.Printf("Arrays and SLices: File: %s, Line: %d\n", file, line)
}
var mySlice []int // Declaring a slice
fmt.Println(mySlice)
mySlice = append(mySlice, 10, 20, 30) // Appending values
fmt.Println(mySlice)
fmt.Println(reflect.TypeOf(mySlice))
// Shorter way
numbers1 := []int{1, 2, 3, 4, 5}
fmt.Println(numbers1) // Output: [1 2 3 4 5]
fmt.Println(reflect.TypeOf(numbers1))
// Creating a slice from an array
arr := [5]int{10, 20, 30, 40, 50}
slice := arr[1:4] // Includes elements from index 1 to 3
fmt.Println(arr, slice) // Output: [20 30 40]
fmt.Println(reflect.TypeOf(arr), reflect.TypeOf(slice))
// printing the addresses of each array element and slice element
// As slice derived from the array, the addresses should match
fmt.Printf("Array addresses:\n")
for i := 0; i < len(arr); i++ {
fmt.Printf("arr[%d]: %p\n", i, &arr[i])
}
fmt.Printf("\nSlice addresses:\n")
for i := 0; i < len(slice); i++ {
fmt.Printf("slice[%d]: %p\n", i, &slice[i])
}
// structures
type Person struct {
Name string
Age int
}
_, file, line, ok = runtime.Caller(0)
if ok {
fmt.Printf("Structs: File: %s, Line: %d\n", file, line)
}
// Initializing a struct
p1 := Person{"Alice", 30}
p2 := Person{Name: "Bob", Age: 25}
fmt.Println(p1, p2) // Output: {Alice 30} {Bob 25}
fmt.Printf("p1: %p, p2: %p\n", &p1, &p2)
fmt.Println(reflect.TypeOf(&p1), reflect.TypeOf(p2))
_, file, line, ok = runtime.Caller(0)
if ok {
fmt.Printf("Maps: File: %s, Line: %d\n", file, line)
}
// Maps
var ages map[string]int // Declaring a map
ages = make(map[string]int) // Initializing the map
if (ages == nil){
fmt.Println(ages) // Output: map[Alice:30 Bob:25]
}
ages["Alice"] = 30
ages["Bob"] = 25
fmt.Println(ages) // Output: map[Alice:30 Bob:25]
// Shorter way
userAges := map[string]int{"Alice": 30, "Bob": 25}
fmt.Println(userAges["Alice"]) // Output: 30
fmt.Println(reflect.TypeOf(ages), reflect.TypeOf(userAges))
var cnt byte
var temp1 uint16 = 900
var temp2 uint32 =6500000
temp2 = 0x999999
fmt.Println(cnt, temp1, temp2)
fmt.Println(reflect.TypeOf(cnt), reflect.TypeOf(temp1), reflect.TypeOf(temp2))
}