├── .gitignore ├── 01-bookstore └── main.go ├── 02-geometry └── main.go ├── 03-empty-interface └── main.go ├── 04-type-assertion └── main.go ├── 05-type-switch └── main.go ├── 06-tank └── main.go ├── 07-find-vowel └── main.go ├── 08-salary-calculator └── main.go ├── 09-receiver-problem └── main.go ├── 10-embedding-interfaces └── main.go ├── 11-multiple-interfaces └── main.go ├── 12-dynamic-json └── main.go ├── 13-http-request └── main.go ├── 14-database-connection └── main.go ├── 15-guitarist └── main.go ├── 16-cars-acceleration └── main.go ├── 17-stringer └── main.go └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | -------------------------------------------------------------------------------- /01-bookstore/main.go: -------------------------------------------------------------------------------- 1 | // https://github.com/inancgumus/learngo/tree/master/interfaces/04-interfaces 2 | 3 | package main 4 | 5 | import "fmt" 6 | 7 | // INTERFACE 8 | 9 | type printer interface { 10 | print() 11 | } 12 | 13 | func main() { 14 | 15 | var ( 16 | mobydick = book{title: "moby dick", price: 10} 17 | minecraft = game{title: "minecraft", price: 20} 18 | tetris = game{title: "tetris", price: 5} 19 | rubik = puzzle{title: "rubik's cube", price: 5} 20 | ) 21 | 22 | var store list 23 | store = append(store, &minecraft, &tetris, mobydick, rubik) 24 | store.print() 25 | 26 | // interface values are comparable 27 | // fmt.Println(store[0] == &minecraft) 28 | // fmt.Println(store[3] == rubik) 29 | } 30 | 31 | // BOOK 32 | type book struct { 33 | title string 34 | price money 35 | } 36 | 37 | func (b book) print() { 38 | fmt.Printf("%-15s: %s\n", b.title, b.price.string()) 39 | } 40 | 41 | func (b book) oku() { 42 | 43 | } 44 | 45 | // GAME 46 | type game struct { 47 | title string 48 | price money 49 | } 50 | 51 | func (g *game) print() { 52 | fmt.Printf("%-15s: %s\n", g.title, g.price.string()) 53 | } 54 | 55 | func (g *game) discount(ratio float64) { 56 | g.price *= money(1 - ratio) 57 | } 58 | 59 | // PUZZLE 60 | type puzzle struct { 61 | title string 62 | price money 63 | } 64 | 65 | func (p puzzle) print() { 66 | fmt.Printf("%-15s: %s\n", p.title, p.price.string()) 67 | } 68 | 69 | // MONEY 70 | type money float64 71 | 72 | func (m money) string() string { 73 | return fmt.Sprintf("$%.2f", m) 74 | } 75 | 76 | type list []printer 77 | 78 | func (l list) print() { 79 | if len(l) == 0 { 80 | fmt.Println("Sorry. We're waiting for delivery 🚚.") 81 | return 82 | } 83 | 84 | for _, it := range l { 85 | fmt.Printf("(%-10T) --> ", it) 86 | 87 | it.print() 88 | 89 | // it.discount(.5) 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /02-geometry/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | type geometry interface { 9 | area() float64 10 | perim() float64 11 | } 12 | 13 | type rect struct { 14 | width, height float64 15 | } 16 | 17 | func (r rect) area() float64 { 18 | return r.width * r.height 19 | } 20 | func (r rect) perim() float64 { 21 | return 2*r.width + 2*r.height 22 | } 23 | 24 | type circle struct { 25 | radius float64 26 | } 27 | 28 | func (c circle) area() float64 { 29 | return math.Pi * c.radius * c.radius 30 | } 31 | func (c circle) perim() float64 { 32 | return 2 * math.Pi * c.radius 33 | } 34 | 35 | func measure(g geometry) { 36 | fmt.Println(g) 37 | fmt.Println(g.area()) 38 | fmt.Println(g.perim()) 39 | } 40 | 41 | func main() { 42 | 43 | r := rect{width: 3, height: 4} 44 | c := circle{radius: 5} 45 | 46 | measure(r) 47 | measure(c) 48 | } 49 | -------------------------------------------------------------------------------- /03-empty-interface/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var i interface{} 7 | describe(i) 8 | 9 | i = 42 10 | describe(i) 11 | 12 | i = "hello" 13 | describe(i) 14 | } 15 | 16 | func describe(i interface{}) { 17 | fmt.Printf("(%v, %T)\n", i, i) 18 | } 19 | -------------------------------------------------------------------------------- /04-type-assertion/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var i interface{} = "hello" 7 | 8 | s := i.(string) 9 | fmt.Println(s) 10 | 11 | s, ok := i.(string) 12 | fmt.Println(s, ok) 13 | 14 | f, ok := i.(float64) 15 | fmt.Println(f, ok) 16 | 17 | f = i.(float64) // panic 18 | fmt.Println(f) 19 | } 20 | -------------------------------------------------------------------------------- /05-type-switch/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func do(i interface{}) { 6 | switch v := i.(type) { 7 | case int: 8 | fmt.Printf("Twice %v is %v\n", v, v*2) 9 | case string: 10 | fmt.Printf("%q is %v bytes long\n", v, len(v)) 11 | default: 12 | fmt.Printf("I don't know about type %T!\n", v) 13 | } 14 | } 15 | 16 | func main() { 17 | do(21) 18 | do("hello") 19 | do(true) 20 | } 21 | -------------------------------------------------------------------------------- /06-tank/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // Creating an interface 6 | type tank interface { 7 | 8 | // Methods 9 | Tarea() float64 10 | Volume() float64 11 | } 12 | 13 | type myvalue struct { 14 | radius float64 15 | height float64 16 | } 17 | 18 | // Implementing methods of 19 | // the tank interface 20 | func (m myvalue) Tarea() float64 { 21 | 22 | return 2*m.radius*m.height + 23 | 2*3.14*m.radius*m.radius 24 | } 25 | 26 | func (m myvalue) Volume() float64 { 27 | 28 | return 3.14 * m.radius * m.radius * m.height 29 | } 30 | 31 | // Main Method 32 | func main() { 33 | 34 | // Accessing elements of 35 | // the tank interface 36 | var t tank 37 | t = myvalue{10, 14} 38 | fmt.Println("Area of tank :", t.Tarea()) 39 | fmt.Println("Volume of tank:", t.Volume()) 40 | } 41 | -------------------------------------------------------------------------------- /07-find-vowel/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | //interface definition 8 | type VowelsFinder interface { 9 | FindVowels() []rune 10 | } 11 | 12 | type MyString string 13 | 14 | //MyString implements VowelsFinder 15 | func (ms MyString) FindVowels() []rune { 16 | var vowels []rune 17 | for _, rune := range ms { 18 | if rune == 'a' || rune == 'e' || rune == 'i' || rune == 'o' || rune == 'u' { 19 | vowels = append(vowels, rune) 20 | } 21 | } 22 | return vowels 23 | } 24 | 25 | func main() { 26 | name := MyString("Sam Anderson") 27 | var v VowelsFinder 28 | v = name // possible since MyString implements VowelsFinder 29 | fmt.Printf("Vowels are %c", v.FindVowels()) 30 | 31 | } 32 | -------------------------------------------------------------------------------- /08-salary-calculator/main.go: -------------------------------------------------------------------------------- 1 | // https://golangbot.com/interfaces-part-1/ 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | ) 7 | 8 | type SalaryCalculator interface { 9 | CalculateSalary() int 10 | } 11 | 12 | type Permanent struct { 13 | empId int 14 | basicpay int 15 | pf int 16 | } 17 | 18 | type Contract struct { 19 | empId int 20 | basicpay int 21 | } 22 | 23 | //salary of permanent employee is the sum of basic pay and pf 24 | func (p Permanent) CalculateSalary() int { 25 | return p.basicpay + p.pf 26 | } 27 | 28 | //salary of contract employee is the basic pay alone 29 | func (c Contract) CalculateSalary() int { 30 | return c.basicpay 31 | } 32 | 33 | /* 34 | total expense is calculated by iterating through the SalaryCalculator slice and summing 35 | the salaries of the individual employees 36 | */ 37 | func totalExpense(s []SalaryCalculator) { 38 | expense := 0 39 | for _, v := range s { 40 | expense = expense + v.CalculateSalary() 41 | } 42 | fmt.Printf("Total Expense Per Month $%d", expense) 43 | } 44 | 45 | func main() { 46 | pemp1 := Permanent{ 47 | empId: 1, 48 | basicpay: 5000, 49 | pf: 20, 50 | } 51 | pemp2 := Permanent{ 52 | empId: 2, 53 | basicpay: 6000, 54 | pf: 30, 55 | } 56 | cemp1 := Contract{ 57 | empId: 3, 58 | basicpay: 3000, 59 | } 60 | employees := []SalaryCalculator{pemp1, pemp2, cemp1} 61 | totalExpense(employees) 62 | 63 | } 64 | -------------------------------------------------------------------------------- /09-receiver-problem/main.go: -------------------------------------------------------------------------------- 1 | // https://golangbot.com/interfaces-part-2/ 2 | package main 3 | 4 | import "fmt" 5 | 6 | type Describer interface { 7 | Describe() 8 | } 9 | type Person struct { 10 | name string 11 | age int 12 | } 13 | 14 | func (p Person) Describe() { //implemented using value receiver 15 | fmt.Printf("%s is %d years old\n", p.name, p.age) 16 | } 17 | 18 | type Address struct { 19 | state string 20 | country string 21 | } 22 | 23 | func (a *Address) Describe() { //implemented using pointer receiver 24 | fmt.Printf("State %s Country %s", a.state, a.country) 25 | } 26 | 27 | func main() { 28 | var d1 Describer 29 | p1 := Person{"Sam", 25} 30 | d1 = p1 31 | d1.Describe() 32 | 33 | var d2 Describer 34 | a := Address{"Washington", "USA"} 35 | d2 = &a 36 | 37 | /* compilation error if the following line is 38 | uncommented 39 | cannot use a (type Address) as type Describer 40 | in assignment: Address does not implement 41 | Describer (Describe method has pointer 42 | receiver) 43 | */ 44 | //d2 = a 45 | 46 | // d2 = &a //This works since Describer interface 47 | //is implemented by Address pointer in line 22 48 | d2.Describe() 49 | 50 | } 51 | -------------------------------------------------------------------------------- /10-embedding-interfaces/main.go: -------------------------------------------------------------------------------- 1 | // https://golangbot.com/interfaces-part-2/ 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | ) 7 | 8 | type SalaryCalculator interface { 9 | DisplaySalary() 10 | } 11 | 12 | type LeaveCalculator interface { 13 | CalculateLeavesLeft() int 14 | } 15 | 16 | type EmployeeOperations interface { 17 | SalaryCalculator 18 | LeaveCalculator 19 | } 20 | 21 | type Employee struct { 22 | firstName string 23 | lastName string 24 | basicPay int 25 | pf int 26 | totalLeaves int 27 | leavesTaken int 28 | } 29 | 30 | func (e Employee) DisplaySalary() { 31 | fmt.Printf("%s %s has salary $%d", e.firstName, e.lastName, (e.basicPay + e.pf)) 32 | } 33 | 34 | func (e Employee) CalculateLeavesLeft() int { 35 | return e.totalLeaves - e.leavesTaken 36 | } 37 | 38 | func main() { 39 | e := Employee{ 40 | firstName: "Naveen", 41 | lastName: "Ramanathan", 42 | basicPay: 5000, 43 | pf: 200, 44 | totalLeaves: 30, 45 | leavesTaken: 5, 46 | } 47 | var empOp EmployeeOperations = e 48 | empOp.DisplaySalary() 49 | fmt.Println("\nLeaves left =", empOp.CalculateLeavesLeft()) 50 | } 51 | -------------------------------------------------------------------------------- /11-multiple-interfaces/main.go: -------------------------------------------------------------------------------- 1 | // https://golangbot.com/interfaces-part-2/ 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | ) 7 | 8 | type SalaryCalculator interface { 9 | DisplaySalary() 10 | } 11 | 12 | type LeaveCalculator interface { 13 | CalculateLeavesLeft() int 14 | } 15 | 16 | type Employee struct { 17 | firstName string 18 | lastName string 19 | basicPay int 20 | pf int 21 | totalLeaves int 22 | leavesTaken int 23 | } 24 | 25 | func (e Employee) DisplaySalary() { 26 | fmt.Printf("%s %s has salary $%d", e.firstName, e.lastName, (e.basicPay + e.pf)) 27 | } 28 | 29 | func (e Employee) CalculateLeavesLeft() int { 30 | return e.totalLeaves - e.leavesTaken 31 | } 32 | 33 | func main() { 34 | e := Employee{ 35 | firstName: "Naveen", 36 | lastName: "Ramanathan", 37 | basicPay: 5000, 38 | pf: 200, 39 | totalLeaves: 30, 40 | leavesTaken: 5, 41 | } 42 | var s SalaryCalculator = e 43 | s.DisplaySalary() 44 | var l LeaveCalculator = e 45 | fmt.Println("\nLeaves left =", l.CalculateLeavesLeft()) 46 | } 47 | -------------------------------------------------------------------------------- /12-dynamic-json/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | //Simple Employee JSON object which we will parse 10 | empJson := `{ 11 | "id" : 11, 12 | "name" : "Irshad", 13 | "department" : "IT", 14 | "designation" : "Product Manager" 15 | }` 16 | 17 | // Declared an empty interface 18 | var result map[string]interface{} 19 | 20 | // Unmarshal or Decode the JSON to the interface. 21 | json.Unmarshal([]byte(empJson), &result) 22 | 23 | //Reading each value by its key 24 | fmt.Println("Id :", result["id"], 25 | "\nName :", result["name"], 26 | "\nDepartment :", result["department"], 27 | "\nDesignation :", result["designation"]) 28 | } 29 | -------------------------------------------------------------------------------- /13-http-request/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "log" 7 | "net/http" 8 | ) 9 | 10 | func main() { 11 | 12 | resp, err := http.Get("https://swapi.dev/api/starships/9") 13 | if err != nil { 14 | log.Fatal(err) 15 | } 16 | defer resp.Body.Close() 17 | 18 | var result map[string]interface{} 19 | 20 | err = json.NewDecoder(resp.Body).Decode(&result) 21 | if err != nil { 22 | log.Fatal(err) 23 | } 24 | 25 | for k, v := range result { 26 | fmt.Println(k, ": ", v) 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /14-database-connection/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type Connector interface { 6 | Connect() 7 | } 8 | 9 | type SQLConnection struct { 10 | conString string 11 | } 12 | 13 | func (s SQLConnection) Connect() { 14 | fmt.Println("SQL " + s.conString) 15 | } 16 | 17 | type OracleConnection struct { 18 | conString string 19 | } 20 | 21 | func (s OracleConnection) Connect() { 22 | fmt.Println("Oracle " + s.conString) 23 | } 24 | 25 | type DBConnection struct { 26 | db Connector 27 | } 28 | 29 | func (c DBConnection) DBConnect() { 30 | c.db.Connect() 31 | } 32 | 33 | func main() { 34 | 35 | sqlConnection := SQLConnection{conString: "Connection is connected"} 36 | con1 := DBConnection{db: sqlConnection} 37 | con1.DBConnect() 38 | 39 | orcConnection := OracleConnection{conString: "Connection is Connected"} 40 | con2 := DBConnection{db: orcConnection} 41 | con2.DBConnect() 42 | 43 | } 44 | -------------------------------------------------------------------------------- /15-guitarist/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type Guitarist interface { 6 | // PlayGuitar prints out "Playing Guitar" 7 | // to the terminal 8 | PlayGuitar() 9 | } 10 | 11 | // BaseGuitarist 12 | type BaseGuitarist struct { 13 | Name string 14 | } 15 | 16 | func (b BaseGuitarist) PlayGuitar() { 17 | fmt.Printf("%s plays the Bass Guitar\n", b.Name) 18 | } 19 | 20 | // AcousticGuitarist 21 | type AcousticGuitarist struct { 22 | Name string 23 | } 24 | 25 | func (b AcousticGuitarist) PlayGuitar() { 26 | fmt.Printf("%s plays the Acoustic Guitar\n", b.Name) 27 | } 28 | 29 | func main() { 30 | var player BaseGuitarist 31 | player.Name = "Paul" 32 | player.PlayGuitar() 33 | 34 | var player2 AcousticGuitarist 35 | player2.Name = "Ringo" 36 | player2.PlayGuitar() 37 | } 38 | -------------------------------------------------------------------------------- /16-cars-acceleration/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type vehicle interface { 8 | accelerate() 9 | } 10 | 11 | // Car 12 | type car struct { 13 | model string 14 | color string 15 | } 16 | 17 | func (c car) accelerate() { 18 | fmt.Println("Accelrating?") 19 | } 20 | 21 | // Toyota 22 | type toyota struct { 23 | model string 24 | color string 25 | speed int 26 | } 27 | 28 | func (t toyota) accelerate() { 29 | fmt.Println("I am toyota, I accelerate fast?") 30 | } 31 | 32 | func doSomething(v vehicle) { 33 | fmt.Println(v) 34 | 35 | } 36 | func main() { 37 | c1 := car{"suzuki", "blue"} 38 | t1 := toyota{"Toyota", "Red", 100} 39 | c1.accelerate() 40 | t1.accelerate() 41 | doSomething(c1) 42 | doSomething(t1) 43 | } 44 | -------------------------------------------------------------------------------- /17-stringer/main.go: -------------------------------------------------------------------------------- 1 | // https://www.digitalocean.com/community/tutorials/how-to-use-interfaces-in-go 2 | 3 | package main 4 | 5 | import "fmt" 6 | 7 | type Article struct { 8 | Title string 9 | Author string 10 | } 11 | 12 | func (a Article) String() string { 13 | return fmt.Sprintf("The %q article was written by %s.", a.Title, a.Author) 14 | } 15 | 16 | type Book struct { 17 | Title string 18 | Author string 19 | Pages int 20 | } 21 | 22 | func (b Book) String() string { 23 | return fmt.Sprintf("The %q book was written by %s.", b.Title, b.Author) 24 | } 25 | 26 | type Stringer interface { 27 | String() string 28 | } 29 | 30 | func Print(s Stringer) { 31 | fmt.Println(s.String()) 32 | } 33 | 34 | func main() { 35 | a := Article{ 36 | Title: "Understanding Interfaces in Go", 37 | Author: "Sammy Shark", 38 | } 39 | Print(a) 40 | 41 | b := Book{ 42 | Title: "All About Go", 43 | Author: "Jenny Dolphin", 44 | Pages: 25, 45 | } 46 | Print(b) 47 | } 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Golang Interface{} Examples and Use Cases 2 | This repos has lots of interface usage and best practice examples. 3 | --------------------------------------------------------------------------------