# go 知识点合辑

* Go
  * (u)int(8|16|32|64)、bool、string、uintptr、byte(=uint8)、rune(=uint32)、float\[32|64]、complex\[64|128]
  * chan、interface、func
  * array、slice、map

    ```
    reserved-keywords:25
    package import    struct  interface   const    map    type     func    
    if        else    for        switch        select    break  continue    goto    return    fallthrough    case    default     defer   range
    go        chan    var
    预定义标识符：内嵌函数和数据类型等
    append iota  len   cap     make  new  copy
    close  imag  print println panic real recover
    true   false nil
    ```

## switch case

* fallthrough : 强制执行后面的case代码

## 函数

* 不支持重载，一个包不能有两个名字一样的函数
* 命名返回值的名字（return可以不指定变量名）

  ```
    func add(a, b int) (c int) {
            c = a + b
            return
    }
  ```

## 可变参数

* 可变参数实际上是一个slice，可以通过arg\[index]依次访问所有参数；通过len(arg)来判断变参的个数

  ```
    func concat(s string, arg ...string) string {
        str := s
        for i := 0; i < len(arg); i++ {
            str += arg[i]
        }
        return str
    }
  ```

## main & init & defer

* Go程序会自动调用init()和main()，所以你不需要在任何地方调用这两个函数
* init()可以在任何package中出现(可选); main()只能用在package main 中(必需)
* defer
  * 当函数返回时，执行defer语句
  * 多个defer语句，按先进后出的方式执行
  * defer语句中的变量，在defer声明时确定变量
  * 触发异常也会走defer语句

## 闭包

* 闭包是一个函数和与其相关的引用环境组合而成的实体
* 函数可以存储到变量中作为参数传递给其它函数，能够被函数动态的创建和返回

  ```
    func Adder() func(int) int {
        var x int
        return func(d int) int {
            x += d
            return x
        }
    }

    f := Adder()
    fmt.Println(f(1))    //1
    fmt.Println(f(10))    //11
    fmt.Println(f(100))    //111
  ```

## 值传递 & 引用传递

* 无论是值传递，还是引用传递，传递给函数的都是变量的副本; 值传递是值的拷贝，引用传递是地址的拷贝
* map、slice、chan、指针、interface默认以引用的方式传递
* new 分配内存，主要用来分配值类型，比如int、struct，返回的是指针
* make 分配内存，主要用来分配引用类型，比如chan、map、slice

## 程序初始化与执行过程

* 程序的初始化和执行都起于main包, 编译时将依赖的包依次导入
* 如果一个包会被多个包同时导入，那么它只会被导入一次
* 流程：
  * 包初始化时，会先逐层递归的将它依赖的包导入进来，直到顶层包。
  * 然后对顶层包中的包级常量和变量进行初始化，接着执行init函数（如果有的话），依次类推，直到最外层包被初始化。
  * 等所有被导入的包加载完毕，就开始对main包中的包级常量和变量进行初始化，然后执行main包中的init函数（如果存在的话），最后执行main函数。

## Array & Slice & Map & Struct

* Array
  * 数组是值类型，当作为方法的入参传入时将复制一份数组而不是引用同一指针；
* Slice
  * 切片是数组的一个容量固定、长度可变的引用，因此切片是引用类型
  * slice 是一个指向array的指针。在传递切片时，等同于传递了一指针。
  * slice 可以自动扩容
* Map
  * 引用类型
* Struct&#x20;
  * 值类型

## range

* 作用于 string or map，可以返回系列 (key, value)

## tag & String() & 类型断言

* tag
  * 在转换成其它数据格式的时候，会使用其中特定的字段作为键值
* String()
  * 如果Interface实现了String()这个方法，那么fmt中默认会调其用String()
* 类型断言
  * 示例

    ```
    func test(i interface{}) {
      n, ok := i.(int)
      if !ok {
          return
      }
      n += 10
    }

    func main() {
      var t1 int
      test(t1)
    }
    ```

## reflect

* reflect.Value.NumField()，获取结构体中字段的个数
* reflect.Value.Method(n).Call(nil)，调用结构体中的方法
* reflect.TypeOf，返回一个Type类型值
* reflect.Value.Kind，返回一个常量，表示变量的类别
* reflect.ValueOf，返回一个Value类型值，该值代表运行时的数据
  * SetXX(x) 因为传递的是x的副本，所以SetXX不能够改x，要改动x必须向函数传递x的指针

    ```
    //> SetInt、SetFloat、SetString

    //错误代码！！！
    //panic: reflect: reflect.Value.SetFloat using unaddressable value
    func main() {
      var a float64
      fv := reflect.ValueOf(&a)
      fv.SetFloat(520.00)
    }
    //正确的，传指针
    func main() {
      var a2 float64
      fv2 := reflect.ValueOf(&a2)
      fv2.Elem().SetFloat(520.00)
      fmt.Printf("%v\n", a2)    //520
    }
    ```

## goroutine

* recover()
* channel
  * chonlyread := make(<-chan int) //创建只读channel&#x20;
  * chonlywrite := make(chan<- int) //创建只写channel   &#x20;


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://joyous-x.gitbook.io/mbook/part-i-language/catalog-1/go_utils.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
