This is a creation in Article, where the information may have evolved or changed.
Type method
1. Defining a method for a type
In the go language, we can define methods for any type, including built-in types, but not pointers and interfaces. For example, in practical programming, we often use []byte's slices, we can define a new type:
Type Byteslice []byte
Then we can define the method. For example, if we don't want to use the built-in append function, we can implement one of our own append methods:
Func Append (Slice, data[]byte) []byte {
L: = Len (slice)
If L + len (data) > Cap (slice) {//Reallocate
Allocate double What's needed, for the future growth.
Newslice: = Make ([]byte, (L+len (data)) * *)
The copy function is predeclared and works for any slice type.
Copy (Newslice, slice)
Slice = Newslice
}
Slice = Slice[0:l+len (data)]
For I, c: = Range Data {
Slice[l+i] = C
}
return slice
}
We can implement our own memory expansion strategy in Append. There is no other difference between this new type and []byte], except that it has one more append method:
var a byteslice = []byte{1,2,3}
B: = []byte{4}
A.append (b)//won ' t change a
Fmt. Println (a)
A = A.append (b)
Fmt. Println (a);
Output:
[1 2 3]
[1 2 3 4]
Note that the Append method above can only be called by Byteslice, not by []byte. In addition, in order to get the updated value, we must return the updated value as the return value, which is clumsy, we can implement the Append method in a more graceful way:
Func (P *byteslice) Append (data[]byte) {
Slice: = *p
L: = Len (slice)
If L + len (data) > Cap (slice) {//Reallocate
Allocate double What's needed, for the future growth.
Newslice: = Make ([]byte, (L+len (data)) * *)
The copy function is predeclared and works for any slice type.
Copy (Newslice, slice)
Slice = Newslice
}
Slice = Slice[0:l+len (data)]
For I, c: = Range Data {
Slice[l+i] = C
}
*p = Slice
}
by using pointers, you can achieve the purpose of modifying the object itself:
var a byteslice = []byte{1,2,3}
var c byteslice = []byte{1,2,3}
B: = []byte{4}
(&a). Append (b)
C.append (b)
Fmt. Println (a)
Fmt. Println (c)
Output:
[1 2 3 4]
[1 2 3 4]
In fact, we can take a step further and we can modify the function to look like the standard write method:
Func (P *byteslice) Write (data []byte) (n int, err error) {
Slice: = *p
L: = Len (slice)
If L + len (data) > Cap (slice) {//Reallocate
Allocate double What's needed, for the future growth.
Newslice: = Make ([]byte, (L+len (data)) * *)
The copy function is predeclared and works for any slice type.
Copy (Newslice, slice)
Slice = Newslice
}
Slice = Slice[0:l+len (data)]
For I, c: = Range Data {
Slice[l+i] = C
}
*p = Slice
Return len (data), nil
}
This type of *byteslice will satisfy the standard interface io.writer:
Package IO
Type Writer Interface {
Write (P []byte) (n int, err error)
}
So that we can print to a variable of that type:
var b byteslice
Fmt. fprintf (&b, "AA%DBB", 7)
Fmt. Println (b)
Output:
[98 98]
Note that this must be passed &b to the FMT. fprintf, if you pass B, the following error is reported at compile time:
Cannot use B (type Byteslice) as type IO. Writer in argument to FMT. fprintf:
Byteslice does not implement IO. Writer (Write method has pointer receiver)
The Go Language specification has this rule:
The method set of any other
named type T consists of all methods with receiver type T. The method set of the corresponding pointer type *t is the set of any methods with receiver *t or T (so is, it also cont Ains the method set of T).
See here. In layman's terms, the object of the pointer type (*T) contains the method that the recipient is T, and vice versa. <effective go> has such a description:
We Pass the address of a byteslice because only *byteslice satisfies IO. Writer. The rule about pointers vs. values for receivers are that value methods can being invoked on pointers and values, but pointer Methods can only is invoked on pointers.
We only define the (P *byteslice) Write method here, and Byteslice does not implement the interface Io.write, so the above error is reported. Note that the description here has a context, which is to assign a value to the interface.
So why in the append example, (&a). Append (b) and C. Append (b) are all OK? Because this is not related to interfaces. We can no longer understand go with C + +, because the object in go does not have this pointer. More frankly, the object itself is passed explicitly as a parameter. So, even if c. Append (b), go will also pass &c to Append method.
Anyway, I think it's a very confusing place to be.
2. Value method and pointer method
In the previous section, we saw the difference between a value method (Method,receiver value) and a pointer method (pointer method,receiver and pointer).
Func (S *mystruct) Pointermethod () {}//method on pointer
Func (S MyStruct) Valuemethod () {}//method on value
So when to use the value method, when to use the pointer method? The main considerations are as follows:
(1) If the method needs to modify receiver, then the pointer method must be used;
(2) If receiver is a large structure, the pointer method should be used in consideration of efficiency;
(3) consistency. If some methods must be pointer receiver, then other methods should also use the pointer receiver;
(4) For some basic types, slices, or small structures, using the value receiver will be more efficient.
Detailed reference here.
3. Example
The practice of adding methods to native data types is common in go language programming, so look at http. Header:
A header represents the Key-value pairs in an HTTP header.
type Header map[string][]string
Add adds the key, value pair to the header.
It appends to any existing values associated with key.
func (H Header) ADD (key, value string) {
Textproto. Mimeheader (h). ADD (key, value)
}
...