217 lines
5 KiB
Go
217 lines
5 KiB
Go
|
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.Println("\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ıkçı", 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)
|
|||
|
}
|