《Google资深工程师深度讲解Go语言》学习笔记 - Go语言中文社区

《Google资深工程师深度讲解Go语言》学习笔记


第1章 Go语言简单介绍

Go语言的设计初衷

1.针对其他语言的痛点进行设计;2.并加入并发编程;3.为大数据、微服务、并发而生的通用编程语言。

Go语言与转型

项目转型首选语言;软件工程师转型、添加技术栈的首选语言;这是一门为转型量身定制的课程。

Go语言很特别:1.没有“对象”,没有继承多态,没有泛型,没有try/catch。2.有接口,函数式编程,CSP并发模型(goroutine+channel)。

示例 语法部分:每个小片段解决实际问题

综合部分:经典算法+典型例题+微型项目

实战项目部分:搭建分布式爬虫,结构复杂

基本语法:变量;选择,循环;指针,数组,容器

面向接口编程:结构体;duck typing的概念;组合的思想

函数式编程:闭包的概念;多样的例题

工程化:资源管理,错误处理;测试和文档;性能调优

并发编程:gorountine和channel;理解调度器;多样的例题

实战项目:从0开始,使用Go语言自主搭建简单分布式爬虫。爬取相亲网站资料;

Go语言的安装与开发环境

下载Go安装包:https://studygolang.com/dl

开发环境:idea + go插件

第2章 基本语法

2-1 变量定义

使用var关键字 

var a, b, c bool

var s1, s2 string = "hello, "world"

可放在函数内,或直接放在包内

使用var()集中定义变量

让编译器自动决定类型

var a, b, i, s1, s2 = true,false, 3, "hello", "world"

使用:=定义变量,只能在函数内使用

a, b, i, s1, s2 := true, false, 3, "hello', "world"

package main

import "fmt"
//函数外定义变量,不是全局变量,是包内变量
var (
   aa = 3
   ss = "kkk"
   bb = true
)

//函数里定义变量
func variableZerovalue() {
   var a int
   var s string
   fmt.Printf("%d %qn", a,s)
}

//变量赋初值
func variableInitialvalue() {
   var a, b int = 3, 4
   var s string = "abc"
   fmt.Println(a, b, s)
}

func variableTypeDeduction() {
   var a, b, c, s = 3, 4, true, "def"
   fmt.Println(a, b, c, s)
}

func variableShorter() {
   a, b, c, s := 3, 4, true, "def"
   b = 5
   fmt.Println(a, b, c, s)
}

func main() {
   fmt.Println("Hello,World!")
   variableZerovalue()
   variableInitialvalue()
   variableShorter()
   fmt.Println(aa, ss, bb)
}

内建变量类型

bool, string

(u)int, (u)int8,(u)int16,(u)int32,(u)int64,uintptr

byte字节类型,rune字符类型32位

float32, float64,complex64实部虚部32位,complex128实部虚部64位

package main

import fmt

func euler() {
    //c := 3 + 4i
    //fmt.Println(complx.Abs(c))
    //fmt.Println(
    //    cmplx.Pow(math.E, 1i * math.Pi) + 1)
    fmt.Printf("%.3fn",
        cmplx.Exp(1i * math.Pi) + 1)
}

func main() {
    euler()
}

强制类型转换

类型转换是强制的

var a, b int = 3, 4

package main

import fmt

func triangle() {
    var a, b int 3, in
    var c int
    c = int(math.Sqrt(float64(a * a + b * b)))
    fmt.Println(c)
}

func main() {
    triangle()
}

2-3 常量与枚举

常量的定义

const filename = “abc.txt”

const数值可作为各种类型使用
const a, b = 4
var c int = int(math.Sqrt(a*a + b*b))

使用常量定义枚举类型

普通枚举类型

自增值枚举类型
package main

import (
   "fmt"
   "math"
)
//常量定义包内,所有函数都能用。
//const filename = "abc.txt"
func consts() {
   const (
      filename = "abc.txt"
      a, b = 3, 4
   )
   var c int
   c = int(math.Sqrt(a*a + b*b))
   fmt.Println(filename, c)
}

func enums() {
   const (
      cpp = iota
      _
      python
      golang
      javascrip
   )

   //b, kb, mb, gb, tb, pb
   const (
      //iota作为自增值的种子
      b = 1 << (10 * iota)
      kb
      mb
      gb
      tb
      pb
   )
   fmt.Println(cpp, javascrip, python, golang)
   fmt.Println(b, kb, mb, gb, tb, pb)
}
func main(){
   consts()
   enums()
}

变量定义要点回顾

变量类型写在变量名之后

编译器可推测变量类型

没有char,只有rune、

原生支持复数类型

2-4 条件语句

if

if的条件里不需要括号
func bounded(v int) int {
   if v > 100 {
      return 100
   } else if v < 0 {
      return 0
   } else {
      return v
   }
}

if的条件里可以赋值

if的条件里赋值的变量作用域就在这个if语句里
if contents, err := ioutil.ReadFile(filename); err != nil {
fmt.Println(err)
} else {
fmt.Printf("%sn", contents)
}

 

package main

import (
   "io/ioutil"
   "fmt"
)

func main() {
   const filename = "abc.txt"
   if contents, err := ioutil.ReadFile(filename); err != nil {
      fmt.Println(err)
   } else {
      fmt.Printf("%sn", contents)
   }
/* if err != nil {
      fmt.Println(err)
   } else {
      fmt.Printf("%sn", contents)
   }*/
}

switch
switch会自动break,除非使用fallthrough

switch后可以没有表达式
func eval(a, b int, op string) int {
   var result int
   switch op {
   case "+":
      result = a + b
   case "-":
      result = a - b
   case "*":
      result = a * b
   case "/":
      result = a / b
   default:
      //panic报错
      panic("unsupported operator:" + op)
   }
   return result
}

 

package main

import (
   "io/ioutil"
   "fmt"
)

func grade(score int) string {
   g := ""
   switch {
   case score < 0 || score > 100:
      panic(fmt.Sprintf(
         "Wrong score: %d", score))
   case score < 60:
      g = "F"
   case score < 80:
      g = "C"
   case score < 90:
      g = "B"
   case score <= 100:
      g = "A"
   }
   return g
}
func main() {
   fmt.Println(
      grade(0),
      grade(59),
      grade(60),
      grade(82),
      grade(99),
      grade(100),
      grade(103),
   )
}

2-5 循环

for
sum := 0
for i := 1; i <= 100; i++ {
   sum += 1
}
for的条件里不需要括号
for的条件里可以省略初始条件,结束条件,递增表达式

package main

import (
   "fmt"
   "strconv"
   "os"
   "bufio"
)

func convertToBin(n int) string {
   result := ""
   for ; n > 0; n /= 2 {
      lsb := n % 2
      result = strconv.Itoa(lsb) + result
   }
   return result
}

func printFile(filename string) {
   file, err := os.Open(filename)
   if err != nil {
      panic(err)
   }

   scanner := bufio.NewScanner(file)

   for scanner.Scan() {
      fmt.Println(scanner.Text())
   }
}
//死循环
func forever() {
   for {
      fmt.Println("abc")
   }
}
func main() {
   fmt.Println(
      convertToBin(5), //101
      convertToBin(13), //1101
      convertToBin(72337885), //
      convertToBin(0), //
   )
   printFile("abc.txt")
   forever()
}

省略初始条件,相等于while

func convertToBin(n int) string {
   result := ""
   for ; n > 0; n /= 2 {
      lsb := n % 2
      result = strconv.Itoa(lsb) + result
   }
   return result
}

省略初始条件,相等于while
for scanner.Scan() {
      fmt.Println(scanner.Text())
   }
无限循环

for {
      fmt.Println("abc")
   }

基本语法要点回顾:

for, if后面的条件没有括号
if条件里也可以定义变量
没有while
switch不需要break,也可以直接switch多个条件

2-6 函数

函数
func eval(a, b int, op string) int

函数可返回多个值:

func div(a, b int) (int, int) {
   return a / b, a % b
}

 

函数返回多个值时可以起名字

仅用于非常简单的函数

对于调用者而言没有区别

func div(a, b int) (q, r int) {
     q = a / b

 r = a % b

return
}

 

package main

import (
   "fmt"
   "reflect"
   "runtime"
   "math"
)

func eval(a, b int, op string) (int, error) {
   switch op {
   case "+":
      return a + b, nil
   case "-":
      return a - b, nil
   case "*":
      return a * b, nil
   case "/":
      q, _ := div(a, b)
      return q, nil
   default:
      return 0, fmt.Errorf(
         "unsupported operation: %s", op)
   }
}

// 13 / 3 = 4 ... 1
func div(a, b int) (q, r int) {
   return a / b, a % b
}
//函数式编程
func apply(op func(int, int) int, a, b int) int {
   p := reflect.ValueOf(op).Pointer()
   opName := runtime.FuncForPC(p).Name()
   fmt.Printf("Calling function %s with args " +
      "(%d, %d)n", opName, a, b)
   return op(a, b)
}

/*func pow(a, b int) int {
   return int(math.Pow(float64(a), float64(b)))
}*/

 

//可变参数列表
func sum(numbers ...int) int {
   s := 0
   for i := range numbers {
      s += numbers[i]
   }
   return s
}


func main() {
   if result, err := eval(3, 4, "x"); err!= nil{
      fmt.Println("Error:", err)
   } else {
      fmt.Println(result)
   }
   q, r := div(13, 3)
   fmt.Println(q, r)

   fmt.Println(apply(
      func(a int, b int) int {
         return int(math.Pow(
            float64(a), float64(b)))
      }, 3, 4))

fmt.Println(sum(1, 2, 3, 4, 5))


}

函数式参数也可以是一个函数,也可以写一个匿名函数来调它

函数作为参数:
func apply(op func(int, int) int, a, b int) int {
   fmt.Printf("Calling function %s with %d, %dn",
      runtime.FuncForPC(reflect.ValueOf(op).Pointer()).Name(),
      a, b)
   return op(a, b)
}

可变参数列表:

func sumArgs(values ...int) int {
   s := 0
   for i := range values{
      sum += values[i]
   }
   return sum
}

函数语法要点回顾:

返回值类型写在最后面

可返回多个值

函数作为参数

没有默认参数,可选参数

2-7 指针
指针不能运算
var a int = 2
var pa *int = &a
*pa = 3
fmt.Println(a)
参数传递
Go语言只有值传递一种方式

 

拷贝一份a的地址,使用指针传递相当于引用传递的效果

 

Go语言中Object类型的名字叫Cache

 

package main

import (
   "fmt"
)

func swap(a, b int) (int, int){
   return b, a
}
func main() {
   a, b := 3, 4
   a, b = swap(a, b)
   fmt.Println(a, b)
}
第3章 内建容器

 

 

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/niwoxiangyu/article/details/95982725
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-03-06 22:21:55
  • 阅读 ( 1612 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢