go-learning/3methods/interfaces.go

216 lines
5 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"fmt"
"math"
"reflect"
)
type Abser interface {
Abs() float64
}
type I interface {
M()
}
type I2 interface {
C()
}
type Vertex struct {
X, Y float64
}
type Vertex2 struct {
X, Y float64
}
type T struct {
S string
}
type MyFloat float64
func main() {
fmt.Println("An interface type is defined as a set of method signatures")
var f Abser = MyFloat(1.2)
var va Abser = &Vertex{3, 4}
var v Abser = Vertex2{3, 4}
// var v Abser = Vertex{3, 4} // ERROR, Same Vertex type not work because interface recognize them as same type
fmt.Println(f.Abs()) // goes to `func (f MyFloat) Abs() float64 {`
fmt.Println(va.Abs()) // goes to `func (v *Vertex) Abs() float64 {`
fmt.Println(v.Abs()) // goes to `func (v Vertex2) Abs() float64 {`
fmt.Println(reflect.TypeOf(f), reflect.TypeOf(f).Kind())
fmt.Println(reflect.TypeOf(va), reflect.TypeOf(va).Kind())
fmt.Println(reflect.TypeOf(v), reflect.TypeOf(v).Kind())
/*
TODO No need to interfaces ?
```
f := MyFloat(1.2)
va := &Vertex{3, 4}
v := Vertex2{3, 4}
```
Also this code block works even with Abser interface removed ?
---
Also in this example: https://github.com/Furkan-Gulsen/turkce-go-egitimi#interfaces
There is no need to interfaces, just remove the interface and use methods normally as circle.area(), square.area() ...
What is our motivation to use Interfaces ???
*/
// TODO what's the point! https://go.dev/tour/methods/10
// TODO In this example describe function uses Interface as argument. And this prevents multiple describe function. Is it a use case for interfacse (https://go.dev/tour/methods/11)
// TODO LOOK FOR HEAD-FIRST-GO EXAMPLES
// LINK https://www.digitalocean.com/community/tutorials/how-to-use-interfaces-in-go
// LINK https://duncanleung.com/understand-go-golang-interfaces/
// LINK https://research.swtch.com/interfaces
// TODO Understand interfaces more !
fmt.Printf("\n\n")
fmt.Println("If the concrete value inside the interface itself is nil, the method will be called with a nil receiver")
var i I
var t *T
i = t
describe(i)
i.M()
i = &T{"hello"}
describe(i)
i.M()
fmt.Printf("\n")
fmt.Println("A nil interface value holds neither value nor concrete type")
var i2 I2
describe2(i2)
// i2.C() // panic: runtime error: invalid memory address or nil pointer dereference
fmt.Printf("\n\n")
fmt.Println("The interface type that specifies zero methods is known as the empty interface:")
var i3 interface{}
describe3(i3)
fmt.Println("An empty interface may hold values of any type")
i3 = 43
describe3(i3)
i3 = "hello"
describe3(i3)
fmt.Println("Empty interfaces are used by code that handles values of unknown type")
fmt.Printf("\n\n")
fmt.Println(" A type assertion provides access to an interface value's underlying concrete value. Can be used with t:=i.(T)")
var i4 interface{} = "hello"
s := i4.(string)
fmt.Println(s)
fmt.Println("You can also test if type is true with two variable. This also prevents panic")
s, ok := i4.(string)
fmt.Println(s, ok)
f2, ok := i4.(float64)
fmt.Println(f2, ok) // 0 false
// f3 := i4.(float64) // panic: interface conversion: interface {} is string, not float64
// fmt.Println(f3)
fmt.Printf("\n\n")
fmt.Println("You can also use interfaces for getting a variable as argument and then deciding type of this variable. var.(type) returns interfaces type. And then you can check different types with switch-case")
somevar(61)
somevar("hello")
fmt.Printf("\n\n")
fmt.Println("One of the most ubiquitous interfaces is Stringer defined by the fmt package. A Stringer is a type that can describe itself as a string. he fmt package (and many others) look for this interface to print values.")
/*
type Stringer interface {
String() string
}
*/
fmt.Println("This means you can change output style with String() method for a type")
myVarA := Person{"Aliberk Sandıı", 50}
myVarB := Person{"Burak", 100}
myVarC := Person2{"Kemal", 150}
fmt.Println(myVarA, myVarB, myVarC)
}
type Person struct {
Name string
Age int
}
func (p Person) String() string {
return fmt.Sprintf("%s + %d, ", p.Name, p.Age)
}
type Person2 struct {
Name string
Age int
}
func (p Person2) String() string {
return fmt.Sprintf("%s ! %d", p.Name, p.Age)
}
func somevar(i interface{}) {
switch v := i.(type) {
case int:
fmt.Printf("INT: %v, %T\n", v, v)
case string:
fmt.Printf("STRING: %v, %T\n", v, v)
default:
fmt.Printf("OTHER: %v, %T\n", v, v)
}
// fmt.Println( i.(type) ) // Can't be used outside of switches!
}
func (f MyFloat) Abs() float64 {
if f < 0 {
return float64(-f)
}
return float64(f)
}
func (v *Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func (v Vertex2) Abs() float64 {
return math.Sqrt(v.X*v.X+v.Y*v.Y) + 10
}
func (t *T) M() {
if t == nil {
fmt.Println("<nil>")
return
}
fmt.Println(t.S)
}
func describe(i I) {
fmt.Printf("(%v, %T)\n", i, i)
}
func describe2(i I2) {
fmt.Printf("(%v, %T)\n", i, i)
}
func describe3(i interface{}) {
fmt.Printf("(%v, %T)\n", i, i)
}