美文网首页Golang 入门资料+笔记
《GO语言圣经》学习笔记(一)

《GO语言圣经》学习笔记(一)

作者: 半亩房顶 | 来源:发表于2020-07-23 10:08 被阅读0次

前言

终于开坑go语言圣经了,本系列笔记中会记录学习《GO语言圣经》中看到的知识点和引申学习。好的,话不多说,开始第一章《入门》

入门知识点

Go Range

底层实现:

// Arrange to do a loop appropriate for the type.  We will produce
  //   for INIT ; COND ; POST {
  //           ITER_INIT
  //           INDEX = INDEX_TEMP
  //           VALUE = VALUE_TEMP // If there is a value
  //           original statements
  //   }
  • 针对数组的编译实现:
// The loop we generate:
//   len_temp := len(range)
//   range_temp := range
//   for index_temp = 0; index_temp < len_temp; index_temp++ {
//           value_temp = range_temp[index_temp]
//           index = index_temp
//           value = value_temp
//           original body
//   }
  • 针对切片的编译实现:
//   for_temp := range
//   len_temp := len(for_temp)
//   for index_temp = 0; index_temp < len_temp; index_temp++ {
//           value_temp = for_temp[index_temp]
//           index = index_temp
//           value = value_temp
//           original body
//   }

共同的主题是:

  • 所有的一切都只是C风格的循环。
  • 你迭代的东西被赋值给一个临时变量。
  • range表达式只会被赋值一次。(即进入循环前会对切片的长度进行快照,决定一共循环多少次。后面切片的变动不会改变循环次数
  • 补充一点:range以Unicode字符遍历,for循环用utf-8遍历,有中文时,遍历长度不同
  • 针对map的编译实现:
  // The loop we generate:
  //   var hiter map_iteration_struct
  //   for mapiterinit(type, range, &hiter); hiter.key != nil; mapiternext(&hiter) {
  //           index_temp = *hiter.key
  //           value_temp = *hiter.val
  //           index = index_temp
  //           value = value_temp
  //           original body
  //   }

遍历map时初始化源码如下

func mapiterinit(t *maptype, h *hmap, it *hiter) {
    ...
    it.t = t
    it.h = h
    it.B = h.B
    it.buckets = h.buckets
    if t.bucket.kind&kindNoPointers != 0 {
        h.createOverflow()
        it.overflow = h.extra.overflow
        it.oldoverflow = h.extra.oldoverflow
    }

    // 重点看这里!!!
    r := uintptr(fastrand())
    if h.B > 31-bucketCntBits {
        r += uintptr(fastrand()) << 31
    }
    it.startBucket = r & bucketMask(h.B)
    it.offset = uint8(r >> h.B & (bucketCnt - 1))
    it.bucket = it.startBucket
    ...

    mapiternext(it)
}

可以注意下,重点关注标注的位置,起始位置是通过fastrand()这个随机函数影响的,所以可想而知,map的遍历从结果上看,是“无序”的

goroutine

goroutine是一種函數的併發執行方式,而channel是用來在goroutine之間進行參數傳遞。main函數也是運行在一個goroutine中,而go function則表示創建一個新的goroutine,併在這個這個新的goroutine里執行這個函數。

指針

Go語言提供了指針。指針是一種直接存儲了變量的內存地址的數據類型。在其它語言中,比如C語言,指針操作是完全不受約束的。在另外一些語言中,指針一般被處理爲“引用”,除了到處傳遞這些指針之外,併不能對這些指針做太多事情。Go語言在這兩種范圍中取了一種平衡。指針是可見的內存地址,&操作符可以返迴一個變量的內存地址,併且*操作符可以獲取指針指向的變量內容,但是在Go語言里沒有指針運算,也就是不能像c語言里可以對指針進行加或減操作

一個指針的值是另一個變量的地址。一個指針對應變量在內存中的存儲位置。併不是每一個值都會有一個內存地址,但是對於每一個變量必然有對應的內存地址。通過指針,我們可以直接讀或更新對應變量的值,而不需要知道該變量的名字(如果變量有名字的話)。

引用

Go Range循环的真相
为什么遍历 Go map 是无序的?


欢迎大家关注我的公众号


半亩房顶

相关文章

  • 笨办法学golang(三)

    这是Go语言学习笔记第三篇。 Go语言学习笔记参考书籍「Go语言圣经」以及Go官方标准库 Go语言基本类型主要有布...

  • 笨办法学golang(四)

    这是Go语言学习笔记的第四篇 Go语言学习笔记参考书籍「Go语言圣经」以及Go官方标准库 数组 数组是指一系列同类...

  • 《GO语言圣经》学习笔记(一)

    前言 终于开坑go语言圣经了,本系列笔记中会记录学习《GO语言圣经》中看到的知识点和引申学习。好的,话不多说,开始...

  • Golang聚合

    教程 Go Web 编程Go语言圣经(中文版) Tips Golang 学习笔记——交叉编译 & 部署Golang...

  • 笨办法学golang(二)

    这是Go语言学习笔记的第二篇文章。 Go语言学习笔记参考书籍「Go语言编程」、Go官方标准库 前文提要 上篇文章中...

  • 48.Go语言书籍

    Go语言圣经(中文版) Go语言高级编程(Advanced Go Programming https://godo...

  • Go 语言圣经-习题汇总(Go 程序设计语言/The Go Pr

    本文针对 Go 语言圣经 - 《Go 程序设计语言/The Go Programming Language》的所有...

  • Go语言学习资料汇总

    From - 自由编程 入门 首先介绍一本Go语言经典入门书籍Go语言圣经对于入门学习,首先推荐以读书为主,可以辅...

  • 《GO语言圣经》学习笔记(六)函数

    知识点 bare return 如果一个函数将所有的返回值都显示的变量名,那么该函数的return语句可以省略操作...

  • 《GO语言圣经》学习笔记(三)数组

    数组实现原理 与大多数语言实现一样,数组是在内存中分配了一段连续的内存空间: 编译期间的数组类型是由上述的 cmd...

网友评论

    本文标题:《GO语言圣经》学习笔记(一)

    本文链接:https://www.haomeiwen.com/subject/rwxmhktx.html