Method
Go has no class. However, you can still define methods on the struct type.
Method ReceiverAppears infunc
In the parameter between the keyword and the method name.
package mainimport ("fmt""math")type Vertex struct {X, Y float64}func (v *Vertex) Abs() float64 {return math.Sqrt(v.X*v.X + v.Y*v.Y)}func main() {v := &Vertex{3, 4}fmt.Println(v.Abs())}
Method (continued)
In fact, you canArbitraryAny type definition method, not just for struct.
You cannot define methods of types or basic types from other packages.
package mainimport ("fmt""math")type MyFloat float64func (f MyFloat) Abs() float64 {if f < 0 {return float64(-f)}return float64(f)}func main() {f := MyFloat(-math.Sqrt2)fmt.Println(f.Abs())}
Method in which the receiver is a pointer
The method can be associated with the pointer of the naming type or naming type.
TwoAbs
Method. One is in*Vertex
Pointer type, while the otherMyFloat
Value Type. There are two reasons to use the pointer receiver. First, avoid copying values in each method call (it is more efficient if the value type is a large struct ). Second, the method can modify the value pointed to by the receiver.
Try to modifyAbs
At the same timeScale
UsageVertex
Replace*Vertex
As the receiver.
Whenv
YesVertex
TimeScale
Method does not have any effect. 'Scale' modify 'V '. Whenv
Is a value (non-pointer), the method isVertex
And cannot modify the original value.
Abs
The same way. However, only 'V' is read '. Therefore, reading the original value (via pointer) or the copy of that value does not matter.
package mainimport ("fmt""math")type Vertex struct {X, Y float64}func (v *Vertex) Scale(f float64) {v.X = v.X * fv.Y = v.Y * f}func (v *Vertex) Abs() float64 {return math.Sqrt(v.X*v.X + v.Y*v.Y)}func main() {v := &Vertex{3, 4}v.Scale(5)fmt.Println(v, v.Abs())}
Interface
An interface type is a set defined by a set of methods.
The value of the interface type can store any value that implements these methods.
Note:The Code on the left will cause compilation failure.
BecauseAbs
Only defined in*Vertex
'. SoVertex
Does not meet 'abser '.
Package mainimport ("FMT" "math") type abser interface {ABS () float64} func main () {var A abserf: = myfloat (-math. sqrt2) V: = vertex {3, 4} A = f // A myfloat implements absera = & V // A * vertex to implement the following line of abser, V is a vertex (rather than * vertex) // so no abser is implemented. A = vfmt. println (. ABS ()} type myfloat float64func (F myfloat) ABS () float64 {if F <0 {return float64 (-f)} return float64 (f )} type vertex struct {x, y float64} func (V * vertex) ABS () float64 {return math. SQRT (v. x * v. X + v. y * v. Y )}
Implicit Interface
Types are implemented by implementing those methods.
There is no need for explicit declaration.
The implicit interface decouples the packages that implement the interface and the packages that define the interface: they do not depend on each other.
Therefore, you do not need to add a new interface name for each implementation, which also encourages clear interface definitions.
Package Io definedReader
And 'writer'; in fact, you do not have to do this.
Package mainimport ("FMT" "OS") type Reader interface {read (B [] Byte) (N int, err error)} type writer interface {write (B [] Byte) (N int, err error)} type readwriter interface {readerwriter} func main () {var W writer // OS. stdout implements writerw = OS. stdoutfmt. fprintf (W, "Hello, writer \ n ")}
Error
The error is that you can describe anything with a string. The main idea is to return a string from the predefined built-in interface type 'error' and method 'error:
type error interface { Error() string}
When usingfmt
Multiple print functions of the package output oneerror
This method is automatically called.
package mainimport ("fmt""time")type MyError struct {When time.TimeWhat string}func (e *MyError) Error() string {return fmt.Sprintf("at %v, %s",e.When, e.What)}func run() error {return &MyError{time.Now(),"it didn‘t work",}}func main() {if err := run(); err != nil {fmt.Println(err)}}