package main
import "fmt"
func main() {
myString := "dog"
myByte := []byte("cat")
var myInt int = 123456876 // The int, unit and uintptr types are usually 32 bits wide on 32-bit systems and 64 bits wide on 64-bit systems.
var myInt8 int8 = 10
var myInt32 int32 = 123456789
var myInt64 int64 = 34567898765434567
myPString := &myString
myPInt := &myInt
myPByte := &myByte
myPInt8 := &myInt8
myPInt32 := &myInt32
myPInt64 := &myInt64
fmt.Println(getType(myInt)) // int
fmt.Println(getType(myString)) // string
fmt.Println(getType(myByte)) // []uint8
fmt.Println(getType(myInt8)) // int8
fmt.Println(getType(myInt32)) // int32
fmt.Println(getType(myInt64)) // int64
fmt.Println(getType(myPInt)) // *int
fmt.Println(getType(myPString)) // *string
fmt.Println(getType(myPByte)) // *[]uint8
fmt.Println(getType(myPInt8)) // *int8
fmt.Println(getType(myPInt32)) // *int32
fmt.Println(getType(myPInt64)) // *int64
}
func getType(anything interface{}) (string) {
var s string
switch anything.(type) {
case []byte: s = "[]byte"
case string: s = "string"
case int: s = "int"
case int8: s = "int8"
case int32: s = "int32"
case int64: s = "int64"
// pointer
case *[]byte: s = "*[]byte"
case *string: s = "*string"
case *int: s = "*int"
case *int8: s = "*int8"
case *int32: s = "*int32"
case *int64: s = "*int64"
default: s = "unknow"
}
return s
}
There's some key differences between Map and Struct:
- Map is dynamic, you can add/remove keys at runtime. While Struct is fixed.
- Map is using hashing under the hood, so it needs more memory than Struct, and also a bit more slower.
someMap["keyname"]
instead ofsomeStruct.keyname
.- Map is iterable, while Struct is NOT by default.
package main
import "fmt"
type Person struct {
Age int
City string
}
func main() {
// 1. Simple map: Set and Get value
fruitPrices := map[string]float64{
"apple": 1.99,
"banana": 0.99,
}
fmt.Println("Price of apple:", fruitPrices["apple"])
// 2. Map with complex data type (struct)
people := map[string]Person{
"Alice": {Age: 30, City: "New York"},
"Bob": {Age: 25, City: "San Francisco"},
}
// Get a value and check if key exists
if person, exists := people["Alice"]; exists {
fmt.Println("Alice's age:", person.Age, ", City:", person.City)
} else {
fmt.Println("Alice not found")
}
// 3. Iterate over a map
for name, person := range people {
fmt.Println("Name:", name, "Age:", person.Age, "City:", person.City)
}
}
package main
import "fmt"
type MyStruct struct {
Name string
}
func (m MyStruct) ValueMethod() {
m.Name = "Changed in ValueMethod"
fmt.Println("Inside ValueMethod: ", m.Name)
}
func (m *MyStruct) PointerMethod() {
m.Name = "Changed in PointerMethod"
fmt.Println("Inside PointerMethod: ", m.Name)
}
func main() {
example := MyStruct{Name: "Original"}
example.ValueMethod() // Inside ValueMethod: Changed in ValueMethod
fmt.Println("After ValueMethod: ", example.Name) // After ValueMethod: Original
example.PointerMethod() // Inside ValueMethod: Changed in ValueMethod
fmt.Println("After PointerMethod: ", example.Name) // Inside ValueMethod: Changed in ValueMethod
}
In Go, interfaces are the way to implement duck typing.
package main
import "fmt"
// Define an interface for behavior
type Quacker interface {
Quack() string
}
// Define a struct that implements the interface
type Duck struct {
Name string
}
func (d Duck) Quack() string {
return d.Name + " quacks like a duck!"
}
// Define another struct that "quacks"
type Dog struct {
Name string
}
func (d Dog) Quack() string {
return d.Name + " quacks like a dog!"
}
// Function that accepts any type that satisfies the Quacker interface
func describeQuacking(quacker Quacker) {
fmt.Println(quacker.Quack())
}
func main() {
myDuck := Duck{Name: "Daffy"}
myDog := Dog{Name: "Buddy"}
describeQuacking(myDuck) // Daffy quacks like a duck!
describeQuacking(myDog) // Buddy quacks like a dog!
}
If you come across some code and are wondering whether a certain type is a struct
or an interface
, you can usually make a distinction by looking at its name.
interface
in Go are typically named with a verb or an action, representing behaviors or actions that a type should implement. For example, Writer, Reader, and EventRecorderstruct
, on the other hand, are usually nouns that represent a concrete type or an object. Examples include Event, Client, or AzureReconciler
type AzureReconciler struct {
client.Client // interface
Log logr.Logger // interface
Scheme *runtime.Scheme // struct
eventRecorder record.EventRecorder // interface
}
Compose
Compose is achieved through interface in go lang. Following is an example.