I have not been working with Go for a long time, so AS a novice, I have summarized some common problems and pitfalls

Note the use of Pointers in Go

// 1. Null pointer backreference is invalid
package main
func main(a) {
    var p *int = nil
    *p = 0
}
// in Windows: stops only with: <exit code="-1073741819" msg="process crashed"/>
// runtime error: invalid memory address or nil pointer dereference

// 2. Literal or constant references are also illegal
const i = 5
ptr := &i //error: cannot take the address of i
ptr2 := &10 //error: cannot take the address of 10

Copy the code

Go common built-in functions

sort

/ / sort package
import "sort"
sort.Strings(keys)

Copy the code

Close for pipe communication, select for communication switch

type T int
func main(a) {
  c := make(chan T)
  close(c)
}

/ / select usage
var c1, c2, c3 chan int
var i1, i2 int
select {
  case i1 = <-c1:
     fmt.Printf("received ", i1, " from c1\n")
  case c2 <- i2:
     fmt.Printf("sent ", i2, " to c2\n")
  case i3, ok := (<-c3):  // same as: i3, ok := <-c3
     if ok {
        fmt.Printf("received ", i3, " from c3\n")}else {
        fmt.Printf("c3 is closed\n")}default:
     fmt.Printf("no communication\n")}Copy the code

Len, cap,

Len is used to return the length or quantity of a type (string, array, slice, map, and pipe);

Cap is capacity and is used to return the maximum capacity of a certain type (for slices and maps only)

The new, make

Both new and make are used to allocate memory: new for value types and user-defined types, such as custom structures, and make for built-in reference types (slices, maps, and pipes).

They are used like functions, but take types as arguments: new (type), make (type). New (T) allocates the zero value of type T and returns its address, which is a pointer to type T.

It can also be used for basic types: v := new(int). Make (T) returns the initialized value of type T, so it does more work than new. New () is a function, don’t forget the parentheses

Copy, append

Used to copy and join slices

Panic, recover

Both are used for error handling mechanisms

Print and println

The underlying print function, and the FMT package is recommended in a deployment environment

Complex, Real, imag

Operation of complex numbers, the use of a few scenarios

Go does not support function overloading

The main reason why Go does not support this feature is that function overloading requires redundant type matching, which affects performance; No overloading means just a simple function schedule. So you have to give different names to different functions, and we usually give functions names based on their characteristics

If you want to declare an externally defined function, you only need to give the name and signature of the function, not the body of the function:

func flushICache(begin, end uintptr) // implemented externally
Copy the code

Functions can also be used declaratively, as a function type, as in:

type binOp func(int.int) int
Copy the code

The map of Go uses the same variable address all the time

Best practice: Use key and value to read data and address to write data. If you want to assign an address to another map, use temporary variables

  kvMap := make(map[int]int)
  kvMap[0] = 100
  kvMap[1] = 101
  kvMap[2] = 102
  kvMap[3] = 103
  
  for k, v := range kvMap {
    println(k, &k, v, &v)
  }
 
// 0 0xc000049e50 100 0xc000049e48
// 1 0xc000049e50 101 0xc000049e48
// 2 0xc000049e50 102 0xc000049e48
// 3 0xc000049e50 103 0xc000049e48 
Copy the code

Go traversal key, value is the value, not the address

// Version A:
items := make([]map[int]int.5)
for i:= range items {
    items[i] = make(map[int]int.1)
    items[i][1] = 2
}
fmt.Printf("Version A: Value of items: %v\n", items)

// Version B: NOT GOOD!
items2 := make([]map[int]int.5)
for _, item := range items2 {
    item = make(map[int]int.1) // item is only a copy of the slice element.
    item[1] = 2 // This 'item' will be lost on the next iteration.
}
fmt.Printf("Version B: Value of items: %v\n", items2)


Copy the code

Slice map elements should be used by index as in version A. The item obtained in version B is only a copy of the map value, so the real map element is not initialized

Lock and sync bag

Concurrent programming, found in most languages, is used to deal with multiple threads accessing critical resources. The classic approach is to allow only one thread to operate on shared variables at a time. When a variable is changed by one thread (a critical section), we lock it until the thread has finished executing and unlocked it before other threads can access it. The Go locking mechanism uses Mutex in the Sync package as an example. The way to write a Mutex is the same as the way to read a Mutex

mu sync.Mutex

func update(a int) {
  mu.Lock()
  a = xxx
  mu.Unlock()
}

mu2 sync.RWMutex
mu2.RLock()
mu2.RUnlock()
Copy the code

Check out your profile to follow more.