" Pointer method usage scenarios "
In the use of golang structures, we often use value methods and pointer methods. What are the usage scenarios of these two methods? Let's first look at a piece of code:
func main() {
cat := New("little pig", "American Shorthair", "cat")
cat.SetName("monster") // (&cat).SetName("monster")
fmt.Printf("The cat: %s\n", cat)
cat.SetNameOfCopy("little pig")
fmt.Printf("The cat: %s\n", cat)
}
type Cat struct {
name string // 名字。
scientificName string // 学名。
category string // 动物学基本分类。
}
//构造一个cat实例
func New(name, scientificName, category string) Cat {
return Cat{
name: name,
scientificName: scientificName,
category: category,
}
}
//传指针设置cat名字
func (cat *Cat) SetName(name string) {
cat.name = name
}
//传入值
func (cat Cat) SetNameOfCopy(name string) {
cat.name = name
}
func (cat Cat) String() string {
return fmt.Sprintf("%s (category: %s, name: %q)",
cat.scientificName, cat.category, cat.name)
}
In this example, we set two methods for Cat, SetName is a method of passing pointers, and SetNameOfCopy is a method of passing values. The receiver type of the method SetName is Cat. The left side of Cat represents the pointer type of the Cat type. We can see by running the above example that the receiver of a value method is a copy of the value of the type to which the method belongs. The receiver of a pointer method, on the other hand, is a copy of the pointer value of the primitive value to which the method belongs. We modify the value pointed to by the copy in such a method, but it will definitely reflect the original value.
in the daily development process
1) If you just read the structure variable, you can pass the reference directly without using the pointer. If the pointer is passed by value, the gc will basically not be used. The disadvantage is that the entire struct will be copied in memory . Of course, if it is recognized by the compiler as an inline function, nothing will happen, and it will be very fast. When your function input/return parameter is a relatively simple structure, such as int float, please use pass by value.
Off topic: what are inline functions in golang?
Stack allocation is much more efficient than heap allocation, so we want objects to be allocated on the stack as much as possible. In Go, a goroutine will have a separate stack, and the stack will contain multiple stack frames. The stack frame is the area allocated for the function on the stack when the function is called. But in fact, there are some fixed overheads for function calls, such as maintaining frame pointer register BP, stack overflow detection, etc. Therefore, for some functions with relatively few lines of code, the compiler tends to expand them at compile time to eliminate function calls. This behavior is inlining. If you don't want to disable optimization globally, you can prevent the compiler from inlining the function by adding the //go:noinline pragma when the function is defined.
2) If you need to modify the instance, use the pointer. The pointer is similar to passing by reference. The scope will go to gc, of course, it is not absolute. For example, the return of the pointer from the inline function will not necessarily lead to heap allocation. The global variable memory of reference type in golang is allocated in On the heap, global variables of value type are allocated on the stack, and the built-in new and make, map, slice, etc. are allocated on the heap and must go to gc. The consequence of gc for intensive computing services is that a lot of CPU calculations are consumed on gc, which seriously affects performance.
Off topic: what is a stack?
Heap In programming, the heap is the memory that the application requests the operating system to allocate to itself when it is running. Take a C/C++ program as an example. When using it, we need to actively apply for it (through malloc/New) and use it up. Active release, or reclaimed by the operating system when the program ends, will result in memory fragmentation.
Stack (Stack) The stack (Stack) is a specific area of computer memory, which is generally allocated and released automatically by the CPU. The data structure is characterized by first-in, first-out (FIFO—first in first out). Because the CPU organizes memory efficiently, reading and writing stack variables is very fast, and there is no memory fragmentation.
The difference between Heap and Stack
-
The stack is generally allocated and released by the operating system, and the heap is applied for creation and release by the programmer through the programming language;
-
The stack is used to store function parameters, return values, local variables, temporary contexts when the function is called, etc. As long as the data is local and occupies a certain space, it is generally stored in the Stack, otherwise it is placed in the Heap;
-
The access speed of the stack is relatively faster than that of the heap;
-
Generally speaking, Stack is exclusive to threads, and Heap is shared by threads;
-
When the Stack is created, the size is determined, and the size of the Heap is indeterminate and can be increased freely;
In C/C++ threads, the default thread stack size on most architectures is about 2MB ~ 4MB. If the program runs hundreds or even thousands of threads at the same time, it will take up a lot of memory space and bring other extra overhead. The execution context is considered to be lightweight at design time, so it implements Goroutine as the execution context in user mode, and the minimum stack space is only 2KB. So very efficient.
To sum up, having more pointers does not necessarily increase performance. It may increase the pressure on gc, thereby reducing performance. If you need to modify the instance, use the pointer, and use the non-pointer version if you don't need it. If you are not sure what to use, you can use the pointer receive
Allocation Efficiency in High-Performance Go Services
https://segment.com/blog/allocation-efficiency-in-high-performance-go-services/
Inline functions in Go language
https://segmentfault.com/a/1190000040399875
go.dev
https://go.dev/doc/effective_go#pointers_vs_values
uber_go_guide_cn
https://github.com/xxjwxc/uber_go_guide_cn#%E6%8E%A5%E6%94%B6%E5%99%A8-receiver-%E4%B8%8E%E6%8E%A5%E5%8F% A3
luozhiyun`s Blog
https://www.luozhiyun.com/archives/211