Reading notes and sharing of "The Road to Go Language Improvement, Programming Ideas, Methods and Skills from Novice to Master 1"

The road to improvement of Go language, programming ideas, methods and skills from novice to master

reading sharing

1 book location

Novice --> master, in-depth learning level

  • Programming Thinking : Go Design Philosophy, Writing Go with Go Thinking

  • Practical skills : improve Go code quality (go language standard library and excellent Go open source library project structure, code style, implementation, interface, concurrency, error handling, etc.)


2 Overview of the contents of this book

1. Know everything about Go

  • The birth and evolution of go, language version
  • go's design philosophy
  • Go's native programming thinking

2. Project structure, code style and identifier naming

  • Go typical project structure
  • Format source gofmt
  • go naming convention

3. Declarations, types, statements and control structures

  • Variable declaration form, untyped constant, iota implements enumeration constant, zero value available type, composite literal value as initial value constructor
  • Implementation principles and usage of slices, maps, and strings
  • Package imports, order of expression evaluation, code blocks and scope
  • Control Statement Idioms

4. Functions and methods

  • init function, function, defer
  • method, method of interface
  • variable length parameter

5. Interface

  • Internal representation of interface variables
  • define small interface
  • Avoid using empty interfaces as parameter types
  • Use interface decoupling

6. Concurrent programming

  • Prioritize concurrency design, understand goroutinue scheduling principle, go concurrency model
  • channel、sync、stomic包

7. Error handling

  • common strategy
  • if err!=nil
  • panic

3 Reasons for choosing this book

need:

  • Finally, the code can work, and the code is rotten like shit
  • In actual online use, a bunch of new bugs were discovered, logical loopholes, situations not covered, code bugs, constant iterative repairs...

Summarize:

  • Code standardization and simplicity
    • The overall structure, the folder under which the go file is placed can be well guaranteed
    • Code implementation, elegant and efficient, simple and easy to read
    • Code reuse, when do you need to abstract new methods so that the code will not be bloated and redundant, where should the abstracted code be placed
    • Code decoupling, design patterns involved, code combination, code abstraction

4 small gains to share

Articles 7-12 really don’t know how to name them

Go standard library code: simple and consistent, with context-assisted naming

  • Don't use combinations of words when you can name them with one word
  • Can be represented by a single letter, not a complete letter
strings.Reader() 			 //[good]
strings.StringReader() 	     //[bad]

variable, type, function, method

  • Use a single letter for loops and condition variables (to maintain consistency)
  • Methods, parameters, and return values ​​are mostly single words
  • Functions and types usually have multiple words
  • Declaration and use as close as possible
userSlice  []*User   [bad] // 变量名字不要带类型信息
users      []*User   [good] 

for i,v := range s{
    
     // 利用上下文,让短名字携带更多信息
    
}
t := time.Now()
b := make([]byte,10)

Statement consistency, statement clustering, proximity principle

var(
    a = 1
    f = float32(3.14)   // VS f float32 = 3.14
)

zero value available

var temp []int  
temp = append(temp,2)// 切片零值可用
var m map[string]int  
m = make(map[string]int,0) // map零值不可用

It is recommended to use the composite literal value of field: value for structure and map construction

p := &pipe{
    
    
    wrCh:xxxx,
    rdCh:xxx,
}

Articles 13-19 can be used - how to use them better

Slicing: Try to use the cap parameter to create slices and dynamically expand capacity

var num []int
num := make([]int,23)

map: determine whether the key exists comma ok

if v, ok := Task[username]; !ok {
    
    
	//
}

The construction method of string

s + "hello",最直观
fmt.Sprintf("%s%s",s,"hello"),性能最差,可构造多种不同变量构建字符串
strings.join(s,"hello"),平均性能佳
strings.Builder(),能预估最终字符串长度时效率最高
bytes.Buffer(bytes),类似join

turn to Article 19

turn to 17


5 personal summaries

  • The content of each article can be dug deep, but to really master it requires more practice and thinking
  • How familiar with the various toolkits of go, can know, can use when needed, can know better methods
  • Read the source code: deepen the understanding of use, refer to the code style and implementation method
  • dig deep:
    • Flexible use of basic syntax, functions, methods, interfaces
    • In-depth understanding of collection classes: arrays, slices, maps
    • High concurrency: goroutine, channel, sync, automatic
    • memory management

Part 1 Know everything about the Go language

Article 1 Understand the birth and evolution of the Go language

A gopher designed by Rob Pike's wife Renee French, the gopher has since become a symbol of Go programmers around the world.


Clause 2 Select the appropriate Go language version

On August 25, 2018, Go version 1.11 was released. Go 1.11, the first Go release since Russ Cox gave a talk titled "Toward Go 2" at GopherCon 2017, is as much a milestone as Go 1.5 because it introduces the new Go package management Mechanism: Go module.


Item 3. Understand the design philosophy of the Go language

3.1 Pursuit of simplicity, less is more

Go designers advocate the "minimal way" thinking, that is, there is only one way or as few ways as possible to accomplish a thing

3.2 Preference Combination, Orthogonal Decoupling

The design philosophy that the Go language follows is also composition. The most intuitive combined syntax element provided by the Go language is type embedding, which realizes the vertical expansion of functions.

"High cohesion, low coupling" is an eternal criterion for managing complexity in the field of software development. Go also takes this principle to the extreme at the language design level. Go advocates the combination of orthogonal grammatical elements to form the application skeleton, and the interface is the essence of the language born under this philosophy.

3.3 Native Concurrency, Lightweight and Efficient

The goroutines each perform a specific task, and the goroutines are connected through channel+select. The goroutine scheduler performs CPU scheduling. The existence of concurrency encourages programmers to decompose independent calculations during program design, and the native support for concurrency makes the Go language more adaptable to modern computing environments.

3.4 Engineering-oriented, "bring your own battery"

Go provides various high-quality and high-performance functional packages in the standard library, among which net/http, crypto/xx, encoding/xx and other packages fully meet the construction needs of API/RPC web services in the cloud native era. gofmt unifies the coding style of the Go language.


Article 4 Use Go language native programming thinking to write Go code

The naming uses single letters, which can be understood in specific scenarios, such as i in loops, k and v in traversing maps

To make good use of concurrency to solve problems, the thinking of using concurrency to solve problems needs to be strengthened


func Generate(ch chan<- int) {
    
    
    for i := 2; ; i++ {
    
    
        ch <- i
    }
}
 
func Filter(in <-chan int, out chan<- int, prime int) {
    
    
    for {
    
    
        i := <-in
        if i%prime != 0 {
    
    
            out <- i
            fmt.Printf("prime=%d,i=%d\n", prime, i)
        }
    }
    println("Filter over")
}
 
func main() {
    
    
    ch := make(chan int)
    go Generate(ch)
    for i := 0; i < 10; i++ {
    
    
        prime := <-ch
        print(prime, "\n")
        ch1 := make(chan int)
        go Filter(ch, ch1, prime)
        ch = ch1
    }
}

The second part project structure, code style and identifier naming

Item 5 Use a recognized and widely used project structure, typical project structure of Go language

cmd directory: Store the source file of the main package corresponding to the executable file to be built by the project.

pkg directory: stores the library files that the project itself uses and that the main package of the executable file depends on.

Makefile: The Makefile here is the "representative" of the script used by the project build tool, which can represent the script used by any third-party build tool.

go.mod and go.sum: Configuration files used by Go language package dependency management.

vendor directory (optional): vendor is a mechanism introduced by Go version 1.5 to cache specific versions of dependent packages locally in the project.


Article 6 Use gofmt to format the source code before submission

gofmt, goimports, integrate gofmt/goimports with IDE or editor tools


Clause 7 Use Go naming conventions for identifiers

The Go naming convention chooses a concise naming + annotation to assist explanation, rather than a long name.

  • When naming package export identifiers, do not include the package name in the name, for example: strings.Reader VS strings.StringReader
  • Do not include type information in variable names
  • The closer the variable declaration and use is, the better, or declare the variable before it is used for the first time.
  • Use the context to make the shortest name carry enough information, t stands for time, b stands for byte, i stands for index, v stands for value
  • Constants use multi-word combinations, such as defaultMaxMemory
  • Functions and types are often named with multi-word compounds.
  • The convention of Go language is to use "method name + er" to name the interface. For example: Reader, Writer

Part III Declarations, Types, Statements, and Control Structures

Item 8 Use consistent variable declaration form

In order to do a good job in the consistency of variable declarations in the code, it is necessary to clarify whether the variable to be declared is a package-level variable or a local variable, whether to delay initialization, whether to accept the default type, whether to be a branch control variable, and combine the clustering and proximity principles.

Explicitly declare the recommended way

  • var a = int32 (17)
  • var f = float32 (3.14)

Item 9: Use untyped constants to simplify code

Go's untyped constants just have such characteristics as literal values, which make untyped constants do not need explicit type conversion when participating in variable assignment and calculation, thereby simplifying the code


Item 10 Implement enumeration constants with iota

iota is a predefined identifier of the Go language, which represents the offset value (starting from zero) of the position of each constant in the const declaration block (including single-line declarations) in the block.

  • Even if the iota in the same row appears multiple times, its value is the same
  • If you want to skip an iota value, _ = itota, operate

Clause 11 Try to define the types for which zero values ​​are available

Zero values ​​are available, as in slices

image-20220730094923967

Item 12: Use composite literals as initializers

Go recommends using the composite literal value form of field:value to construct values ​​for struct type variables

image-20220730104547885

image-20220730104608842

Article 13 Understand the principle of slice implementation and use it efficiently

The underlying structure of a slice is an array, which is equivalent to an array descriptor (array, len, cap)

insert image description here

initial zero value, zero value available

createData := make(map[string]interface{
     
     })

var verifyTemp *entity.ConvergeTaskStatics

Dynamic expansion:

defects := make([]model.Defect, 0)
defects = append(defects, defect)

snapshots := make([]string, 0)
snapshots = append(snapshots, path)
  • Note: Once the slice cap touches the upper bound of the array, and then append the slice, the slice will create a new array and unbind the original array
  • If you can estimate the number of elements in the underlying array of slices, try to use the cap parameter to create slices to reduce the performance consumption caused by dynamic expansion

Article 14 Understand the principle of map implementation and use it efficiently

  • Does not support zero value available, no value is not nil, panic will be reported when using
var m map[string]int
m["key"] = 1 //panic:assignment to entry in nil map
  • The operation of adding, deleting, checking and modifying, traversing out of order
    • Note that checking if the key does not exist will return a zero value by default. At this time, it is impossible to determine whether the corresponding key exists. Use comma ok to read the value in the map
if v, ok := TaskStatics[staticInVer.UserName]; !ok {
     
     
	//
}
  • The internal implementation of map is similar to that of java, map expansion, non-thread-safe does not support concurrent writing
  • Also in order to reduce the loss caused by frequent expansion, it is recommended to use the cap parameter to create a map

Article 15 Understand the implementation principle of strings and use them efficiently

  • The string is read-only. After slicing, a new underlying storage will be created. Slicing modification has no effect on the original string.
  • Standard library: strings, strconv
  • internal representation, the underlying descriptor
type stringStruct struct{
     
     
	str unsafe.Pointer
    len int
}
  • The construction method of string
s + "hello",最直观
fmt.Sprintf("%s%s",s,"hello"),性能最差,可构造多种不同变量构建字符串
strings.join(s,"hello"),平均性能佳
strings.Builder(),能预估最终字符串长度时效率最高
bytes.Buffer(bytes),类似join

Item 16. Package import of go language

  • The part after import is the path

  • The compilation process uses the package source code that the compilation unit depends on

  • Package source code search path: basic search path GOROOT/GOPATH/module-aware+package import path import

Item 17 Understand the order of evaluation of GO language expressions

n0,n1 = 1,2
n0,n1 = n0+n1,n0

Package-level variable initialization is performed in the order of variable declaration, and each round looks for ready for initialization

var (
    a = c + b
    b = f()
    _ = f()
    c = f()
    d = 3
)
	
func f() int{
     
     
    d++
    return d
}

func main(){
     
     
	fmt.Println(a,b,c,d)
}

1. The first stage: evaluate the expressions at both ends of the equal sign. In the above problem, there are only two expressions n0+n1 and n0 at the right end, so the value is directly brought in to obtain the evaluation result. After evaluation, the statement can be regarded as: n0, n1 = 3, 1;
2. The second stage: assignment. n0 = 3, n1 = 1

Item 18. Understanding Go Code Blocks and Scope

Article 19 Understand the Go language control statement idioms and precautions

  1. When using the if control statement, the " happy path " principle should be followed , and the " happy path " is the code execution path of the success logic. Principle requirements:
  • When an error occurs, return quickly;
  • Do not embed success logic in if-else statements;
  • The execution logic of the "Happy Path" is always on the left in the code layout, so that readers can see the normal logic flow of the function at a glance;
  • The return value of the "happy path" is generally in the last line of the function.
扁平,可读性强
func doSomething() error{
    if 错误逻辑1{// 出现错误时快速返回
        return err
    }
    成功逻辑2// 成功逻辑不要嵌入 if-else 语句中;
    if 错误逻辑2{
        return err
    }
    成功逻辑2
}

嵌套,可读性不佳
func doSomething() error{
    if 成功逻辑1{
        if 成功逻辑2{
            return err
        }else{
            // 错误逻辑1
        }
    }else{
        // 错误逻辑2
    }

}
  1. pit for range

The iteration variable will be reused in each loop of the for range , and the copy of the array is involved in the loop

var m = [...]int{
     
     1, 2, 3, 4, 5}
for i, v := range m' {
     
     

}

// 这样使用
for i, v := range &m {
     
     

}

Part IV Functions and Methods

Item 20 Check the initial state of package-level variables in the init function

The import package follows depth-first, and loads all dependencies

The init function does package-level data initialization and initial status checks

Item 21 Accustom yourself to functions being first-class citizens

Functions can be created and used like normal integer values

Item 22 Use defer to make functions more compact and robust

There are many resources to be released, and defer makes resource release elegant and error-free

Item 23 Understand the nature of methods to choose the correct receiver type

Binding method, it is recommended to bind the pointer type

func(reveiver T\*T)MethodName(参数列表)(返回值列表){
     
     

}

Clause 24 Method Set Determines Interface Implementation

Implicit interface implementation

  • T's method set = reveiver is T
  • *T method collection = receiver is T and *T method
// CheckCollectTask 检查采集上传数据
func (a *appCollectTaskSrvStruct) CheckCollectTask(){
     
     }

The interface is embedded in the interface to realize the combination of complex functions. When there is an interface with the same name, the principle of proximity can also be used.

Item 25 Understand the magic of variadic functions

Status: rarely use variable length parameter design to implement functions or methods

func fmt.Println(a ...interface{
     
     }) (n int, err error)
func append(slice []Type,elems ...Type) []Type
  • Function overloading with variable length parameters
  • Realize function options (now multi-purpose option package parameters)

Part V Interface

Item 26 Understand the internal representation of variables of interface types

type iface struct {
     
     //有方法的接口类型
	tab  *itab
	data unsafe.Pointer
}

type eface struct {
     
     // 无方法的接口类型
	_type *_type // 存储接口的信息
	data  unsafe.Pointer
}

Empty interface type variable: Only when the data content pointed to by _type and data are consistent, can an equal sign be drawn between two empty interface type variables

Item 27 Define small interfaces as much as possible

The smaller the interface, the higher the degree of abstraction, the easier it is to implement and reuse, the more it is biased towards the business layer, the higher the difficulty of abstraction

type Reader interface{
     
     
 Read(...)
}

First abstract the interface, and then split the small interface

Item 28 Try to avoid using empty interfaces as function parameter types

The empty interface does not have any input parameter information, which avoids type checking and causes problems to be discovered at runtime

Item 29 Use interfaces as connection points for horizontal composition of programs

In-depth understanding of the combination logic of the interface, using vertical combination and horizontal combination

Item 30 Use interfaces to improve code testability

Extract the interface, let the interface be called the bridge between code and unit test (TDD)

Part VI Concurrent Programming

Item 31 Prioritize concurrent design

Concurrency is about structure (number of production lines), parallelism is about execution (number of people executing)

Decompose the code execution unit, code = the combination of code fragments, each fragment is executed concurrently

Article 32 Understand the scheduling principle of goroutine

GPM scheduling model

  • G saves the running stack of Goroutine, that is, the state of concurrent tasks. G is not an execution body, and each G needs to be bound to P to be scheduled for execution.
  • For G, P is equivalent to a CPU core, and G can only be scheduled if it is bound to P (in the local runq of P). For M, P provides related execution environment (Context), such as memory allocation status (mcache), task queue (G)
  • M: OS thread abstraction, responsible for scheduling tasks, bound to a certain P, continuously extracting G from P, switching stacks and executing
insert image description here

Item 33 Master the Go concurrency model and common concurrency models

  • based on shared memory
    insert image description here
  • CSP Based on Communication Sequential Process Model
    insert image description here
  • Goroutine, corresponding to P, encapsulates the processing logic of data, as the basic execution unit
  • channel, for goroutine communication and synchronization
  • select, coordinate multiple channels

Article 34 Understand the magic of channels

  • channel + select
  • Application of unbuffered channel in signal transmission and replacement of lock synchronization
  • Application of buffered channel in message queue and counting signal

Item 35 Understand the correct use of the sync package

Item 36 Use the atomic package for more scalable concurrent reads

Part VII Error Handling

Item 37 Learn about the four strategies for error handling

  • Construct error values: error.New, fmt.Errorf
DatabaseError  error = errors.New("数据库错误,请联系开发人员")
ServerError    error = errors.New("服务器错误,请联系开发人员")
  • Transparent error handling strategy: as soon as an error occurs, enter the error handling logic to reduce the coupling between errors and error handling
err := doSomething()
if err != nil {
     
     
    return err
}
  • Error sentinel strategy, swtich + custom err judgment selection path
  • Error value type inspection strategy to get more error value context information
err.(type)
errors.As(err,&错误类型) // 判断两个err是否一致
errors.Is(err,错误类型)
  • Error behavior feature inspection strategy, error information defined by public interface net.Error
type Error interface{
     
     
    error
    Timeout() bool
    Temporary() bool
}

Item 38 Try to optimize recurring if err != nil

Display error handling is a feature of go

  • Improve visual presentation
  • reduce repetitions
    • refactor
    • The check/handle mechanism is also encapsulated into a function
    • Use the built-in error

Item 39 Do not use panic for normal error handling

Use panics as little as possible

typical application

  • Assert the role, prompting potential bugs,
switch 表达式{
     
     
    case 1:
    case 2:
    panic xxx //代码逻辑不会走到这里,但是走到了这里,说明有潜在bug
}
  • Simplify error handling logic (check/hadle mechanism)
  • Use recover to capture panic to prevent goroutinue from exiting http server unexpectedly

Understand panic output stack frame information to help quickly locate bugs

Guess you like

Origin blog.csdn.net/qq_42647903/article/details/128022272