143 lines
3.3 KiB
Go
143 lines
3.3 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
// "math"
|
|
"reflect"
|
|
)
|
|
|
|
type Vertex struct {
|
|
X, Y float64
|
|
}
|
|
|
|
func (v Vertex) Twice() (float64, float64) { // Twice method has a receiver of type Vertex named v
|
|
return (v.X) * 2, (v.Y * 2)
|
|
}
|
|
|
|
func Twice2(v Vertex) (float64, float64) {
|
|
return (v.X) * 2, (v.Y * 2)
|
|
}
|
|
|
|
//func (f float64) Abs() float64 { // ERROR: cannot define new methods on non-local type float64
|
|
//return 1.4}
|
|
|
|
type MyFloat float64 // First declare type
|
|
//Then use this type in a method
|
|
|
|
func (f MyFloat) Abs() float64 {
|
|
if f < 0 {
|
|
return float64(-f)
|
|
}
|
|
return float64(f)
|
|
}
|
|
|
|
func (v Vertex) Mult(f float64) {
|
|
v.X *= f
|
|
v.Y *= f
|
|
fmt.Printf("%p\n", &v)
|
|
}
|
|
|
|
func (v *Vertex) Mult2(f float64) {
|
|
v.X *= f
|
|
v.Y *= f
|
|
fmt.Printf("%p (address of pointer: %p)\n", v, &v)
|
|
}
|
|
|
|
func Mult3(v *Vertex, f float64) {
|
|
v.X *= f
|
|
v.Y *= f
|
|
fmt.Printf("%p (address of pointer: %p)\n", v, &v)
|
|
}
|
|
|
|
func Mult4(v Vertex, f float64) {
|
|
v.X *= f
|
|
v.Y *= f
|
|
fmt.Printf("%p\n", &v)
|
|
}
|
|
func main() {
|
|
fmt.Println("Go doest not have classes, but you can define methods on types")
|
|
|
|
fmt.Println("A method is a function with a special receiver argument")
|
|
|
|
fmt.Println("The Receiver appears between func keyword and the method name")
|
|
|
|
v := Vertex{10, 15}
|
|
fmt.Println(v.Twice())
|
|
|
|
fmt.Println("You can make this with also using regular functions:")
|
|
|
|
fmt.Println(Twice2(v))
|
|
|
|
fmt.Printf("\n\n")
|
|
|
|
fmt.Println("You cannot declare a method with a receiver whose type is defined in another package. Because of that you also cannot use types like int or float64")
|
|
fmt.Println("You can declare a new type for solving this")
|
|
|
|
fmt.Printf("\n")
|
|
|
|
var x MyFloat = 12
|
|
fmt.Println(x, reflect.TypeOf(x), reflect.TypeOf(x).Kind())
|
|
|
|
f := MyFloat(-123.34) // same as `var f MyFloat = 123.34`
|
|
fmt.Println(f.Abs())
|
|
|
|
fmt.Printf("\n\n")
|
|
|
|
fmt.Println("Also pointers can be used as receivers in methods")
|
|
v2 := Vertex{12, 13}
|
|
fmt.Printf("V2: %p\n", &v2)
|
|
v2.Mult(12)
|
|
fmt.Println(v2)
|
|
|
|
fmt.Printf("\n")
|
|
|
|
v3 := Vertex{12, 13}
|
|
fmt.Printf("V3: %p\n", &v3)
|
|
v3.Mult2(12)
|
|
// `(&v3).Mult2(12)` // ! ACTUALLY SAME THING
|
|
fmt.Println(v3)
|
|
|
|
p := &v3
|
|
fmt.Printf("V3: %p, P: %p, (address of p pointer: %p)\n", &v3, p, &p)
|
|
p.Mult2(2)
|
|
fmt.Println(v3, p) // BOTH CHANGED
|
|
|
|
fmt.Printf("\n")
|
|
fmt.Println("Pointers also can be used with functions but we should pass the variables with ampersant")
|
|
|
|
v4 := Vertex{12, 13}
|
|
fmt.Printf("V4: %p\n", &v4)
|
|
// Mult3(v4, 4) // ERROR
|
|
Mult3(&v4, 12)
|
|
fmt.Println(v4)
|
|
|
|
fmt.Printf("\n")
|
|
fmt.Println("Also we can declare our first value as pointer for avoid using ampersant")
|
|
|
|
p2 := &Vertex{12, 13}
|
|
fmt.Printf("P2: %p, (address of p2 pointer: %p)\n", p2, &p2)
|
|
p2.Mult2(2)
|
|
Mult3(p2, 6)
|
|
fmt.Println(p2)
|
|
|
|
fmt.Printf("\n\n")
|
|
fmt.Println("We couldn't use addresses while function requires a normal value in functions. But while using as methods pointers renders it values")
|
|
|
|
myVar1 := Vertex{1, 2}
|
|
Mult4(myVar1, 2) // OK
|
|
// Mult4(&myVar1, 2) // Compile ERRORr
|
|
fmt.Println(myVar1)
|
|
|
|
myPoint1 := &myVar1
|
|
myVar1.Mult(2) //OK
|
|
myPoint1.Mult(2) //ALSO OK, interpreted as (*myPoint1).Mult(2)
|
|
// SAME WITH (*myPoint1).Mult(2)
|
|
|
|
fmt.Println(myVar1)
|
|
fmt.Println(myPoint1)
|
|
|
|
fmt.Printf("\n\n")
|
|
fmt.Println("Using pointer receivers provides more efficent way, bcs there is no copy process")
|
|
fmt.Println("We should avoid using values and pointer receivers together")
|
|
|
|
}
|