Big data development - Go - common problems for novices

It's not long since I really used Go at work, so as a novice, I summarized some common problems and pitfalls

Notes on Pointer use in Go

// 1. Null pointer back reference is illegal
package main
func main() {
    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. Text 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

Common built-in functions in Go language

sort

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

close is used for pipeline communication and select is used for switch of communication

type T int
func main() {
  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")
}    

len,cap

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

cap means capacity. It is used to return the maximum capacity of a certain type (it can only be used for slices and map s)

new,make

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

They are used like functions, but with types as arguments: new (type), make (type). new (T) assigns a zero value of type T and returns its address, that is, a pointer to type T.

It can also be used for the basic type: 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 its parentheses

copy,append

Used to copy and connect slices

panic,recover

Both are used for error handling mechanisms

print,println

The underlying print function. It is recommended to use fmt package in the deployment environment

complex,real,imag

The operation is complex, and there are few usage scenarios

Go does not support function overloading

The main reason why Go language does not support this feature is that function overloading requires redundant type matching, which affects the performance; No overloading means just a simple function scheduling. So you need to give different names to different functions. We usually name functions according to their characteristics

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

func flushICache(begin, end uintptr) // implemented externally

A function can also be used in a declarative manner as a function type, such as:

type binOp func(int, int) int

When Go's map is traversed, the variable address is always the same

Best practice: you can use key and value to read data and address to write data. If you want to assign an address to another map, you need to 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 

Go traverses the key, and 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)

The sliced map element 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 package

Concurrent programming is used in most languages to solve the access of multiple threads to critical resources. The classic practice is that only one thread can operate on shared variables at a time. When a variable is changed by a thread (critical area), we lock it. Other threads can't access it until the thread is completed and unlocked. This locking mechanism of Go language is accessed through Mutex in sync package. The following is an example. In addition, there is a read-write lock, RWMutex, in sync package. Its write Mutex method is the same as Mutex, Read Mutex using the following method

mu sync.Mutex

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

mu2 sync.RWMutex
mu2.RLock()
mu2.RUnlock()
Wu Xie, the third master, is a rookie in the field of big data and artificial intelligence. Please pay more attention! [file](https://img-blog.csdnimg.cn/20210808140919157.png)

Added by Bou on Sun, 26 Dec 2021 08:58:27 +0200