diff --git a/3methods/methods.go b/3methods/methods.go new file mode 100644 index 0000000..9b5ceb6 --- /dev/null +++ b/3methods/methods.go @@ -0,0 +1,143 @@ +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") + +}