go-learning/3methods/methods.go
2023-07-19 14:26:38 +03:00

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")
}