公开学习文档

公开学习文档


go使用

<h2>设置镜像</h2> <pre><code>go env -w GOPROXY=https://goproxy.cn,direct</code></pre> <h2>关于 iota</h2> <ul> <li> <p>第一步:不同 const 定义块互不干扰</p> </li> <li> <p>第二步:所有注释行和空行全部忽略</p> </li> <li> <p>第三步:没有表达式的常量定义复用上一行的表达式</p> </li> <li>第四步:从第一行开始,iota 从 0 逐行加一</li> </ul> <blockquote> <p>参考文档:<a href="https://blog.wolfogre.com/posts/golang-iota/">https://blog.wolfogre.com/posts/golang-iota/</a></p> </blockquote> <h2>传递类型</h2> <ol> <li> <p>数组、结构体都是值传递</p> <p>因为结构体是值传递,所以如果方法的接受者是值,那么就操作的对象就是值的副本。(方法的接收者可以前移,所以相当于传递了一个struct值参数)。另外,如果结构体里有切片等引用类型,即使struct是值传递,但切片还是指向同一个对象</p> </li> <li>slice、ch、map 都是引用传递</li> </ol> <h2>slice 切片</h2> <ol> <li>slice底层是数组</li> </ol> <h2>ch 通道</h2> <ol> <li> <p>同种类型的ch可以比较</p> </li> <li> <p>被 close 后,再尝试发送就会宕机(已发的数据不影响),但是接受不会宕机,而且在收完缓存的数据后,会立即收到零值,可以用 <code>v, ok &lt;- ch</code> 来判断是否通道已经读完一个关闭的通道(也可以用 <code>range</code> 来读取通道,就不用额外关心通道是否关闭)</p> </li> <li> <p>缓冲</p> <pre><code>ch = make(chan int)     //无缓冲通道   ch = make(chan int, 0)  //无缓冲通道</code></pre> </li> <li> <p>单向通道</p> <pre><code>chan&lt;- int    //只能发送的通道   &lt;-chan int    //只能接收的通道   // 注意:close()不能关闭只读通道;双向通道可以转换为单向甬道,反之则不行。</code></pre> </li> <li> <p><code>cap(ch)</code> 可获取其缓冲区大小;<code>len(ch)</code> 可以获取当前通道内的元素个数</p> </li> <li> <p><code>struct{}</code> 作为通道类型,它占用空间为 0</p> </li> <li> <p><code>select</code> 只针对通道的读写动作</p> </li> <li> <p>可以用关闭通道的特性,达到广播结束消息的效果</p> </li> <li> <p><code>select</code> 可以将多个事件串行化,就可以避免加互斥锁</p> </li> <li> <p>循环读取通道用 <code>rang</code>,<code>close</code> 时会自动结束</p> </li> <li>无缓冲通道,可以使流程同步化</li> </ol> <h2>同步机制</h2> <ol> <li> <p>监控变量的 goroutine ,即用 routine 来负责变量的读写</p> </li> <li> <p>避免竟态的方法:用 routine 监控变量;锁机制</p> </li> <li> <p>在设计并发程序时,永远应该优先考虑清晰度,并且拒绝过早优化</p> </li> <li> <p>封装就是隐藏数据,要封装一个对象,必须使用结构体</p> </li> <li> <p>内存同步问题,包括编译器优化,和 cpu 缓存</p> </li> <li>defer 只支持函数,并且参数在定义 defer 的时候就已经取值了。defer 改变返回值:只支持定义了返回值变量的情况</li> </ol> <h2>其它</h2> <ol> <li> <p>读取单个字节</p> <pre><code>is.Stdin.Read(make([]byte, 1))   //读取单个字节</code></pre> </li> <li>struct 内嵌匿名字段(可以是指针类型),可使结构体直接使用内嵌字段的变量和方法。实际上,是编译器根据内嵌字段,来自动生成了外层结构体的方法。</li> </ol> <h2>常见问题</h2> <p>1、协程泄露</p> <pre><code>// 以下,由于 g2 超时退出,导致 g1 无法退出 func leak1() {     ch := make(chan int)     // g1     go func() {         time.Sleep(2 * time.Second) // 模拟 io 操作         ch &lt;- 100                   // 如果 g2 超时退出,这里 g1 就会阻塞住,永远无法退出     }()     // g2     // 阻塞住,直到超时或返回     select {     case &lt;-time.After(500 * time.Millisecond):         fmt.Println("timeout! exit...")     case result := &lt;-ch:         fmt.Printf("result: %d\n", result)     } } // 以下,由于没有关闭 ch,导致 g1 无法退出 func leak2() {     ch := make(chan int)     // 消费者 g1     go func() {         for result := range ch {             fmt.Printf("result: %d\n", result)         }     }()     // 生产者 g2     ch &lt;- 1     ch &lt;- 2     time.Sleep(time.Second)  // 模拟耗时     fmt.Println("main goroutine g2 done...") }</code></pre> <h2>性能优化</h2> <p><code>sync.Pool</code> 可以优化频繁创建、注销的对象。如用于解析 json 的 struct</p> <blockquote> <p>参考文档:<a href="https://geektutu.com/post/hpg-sync-pool.html">https://geektutu.com/post/hpg-sync-pool.html</a></p> </blockquote>

页面列表

ITEM_HTML