Go语言学习

Go语言从入门到实战

2019-05-04  本文已影响0人  开心的锣鼓

一、Go语言背景和发展

1.软件开发的新挑战

2.Go的三位创始人

3.Go语言特点

二、第一个Go程序

[图片上传失败...(image-8dd3db-1556979504914)]

1.应用程序入口

2.退出返回值

3.获取命令行参数

4.基本数据类型

与其他主要编程的差异:

  1. Go语言不允许隐式类型转换
  2. 别名和原有类型也不能进行隐式类型转换

类型的预定义值:

  1. math.MaxInt64
  2. math.MaxFloat64
  3. math.MaxUint32

指针类型

  1. 不支持指针运算
  2. string是值类型,其默认的初始值为空字符串,而不是nil

5.运算符

用 == 比较数组

按位清零运算符

6.循环

Go语言仅支持循环关键字for

for i := 0; i <= 9; I++

7.if条件

  1. condition表达式结果必须为布尔值
  2. 支持变量赋值:
if var declaration; condition {
    
}

8.switch条件

  1. 条件表达式不限制为常量或者整数
  2. 单个case中,可以出现多个结果选项,使用逗号分隔
  3. 与C语言等规则相反,Go语言不需要用break来明确退出一个case
  4. 可以不设定switch之后的条件表达式,在此种情况下,整个switch结构与多个if...else...的逻辑作用等同
switch os := runtime.GOOS; os {
    case "darwin":
        fmt.Println("OS X.")
        //break
    case "linux":
        fmt.Println("Linux.")
    default:
        fmt.Println("%s.",os)
}
switch {
    case 0 <= Num && Num <= 3:
        fmt.Printf("0-3")
    case 4 <= Num && Num <= 6:
        fmt.Printf("4-6")
}
switch I {
    case 0,2:
        fmt.Printf("0-2")
    case 1,3:
        fmt.Printf("1-3")
}

9.Map元素的访问

在访问的Key不存在时,仍会返回零值,不能通过返回nil来判断元素是否存在

if v,ok := map1["key1"]; ok{
    
} else {
    
}

map的遍历

for k,v := range map1{
    
}

10.Map与工厂模式

11.实现Set

Go的内置集合中没有Set实现,可以map[type]bool

  1. 元素的唯一性
  2. 基本操作
    1. 添加元素
    2. 判断元素是否存在
    3. 删除元素
    4. 元素个数

12.字符串

  1. string是数据类型,不是引用或指针类型
  2. string是只读的byte slice,len函数可以它所包含的byte数
  3. string的byte数组可以存放任何数据

13.Unicode UTF8

  1. Unicode是一种字符集(code point)
  2. UTF8是unicode的存储实现(转换为字节序列的规则)

14.常用字符串函数

  1. strings包(https://golang.org/pkg/strings/
  2. strconv包(https://golang.org/pkg/strconv

15.函数是一等公民

  1. 可以有多个返回值
  2. 所有参数都是值传递:slice、map、channel会有传引用的错觉
  3. 函数可以作为变量的值
  4. 函数可以作为参数和返回值

16.Go接口

  1. 接口为非入侵性,实现不依赖接口定义
  2. 所以接口的定义可以包含在接口使用者包内

17.空接口与断言

  1. 空接口可以表示任何类型
  2. 通过断言来将空接口转换为制定类型
v, ok := p.(int) //ok=true时为转换成功

18.Go接口最佳实践

  1. 倾向于使用小的接口定义,很多接口只包含一个方法
type Reader interface {
    Read(p []byte) (n int, err error)
}
type Writer interface {
    Write(p []byte) (n int,err error)
}
  1. 较大的接口定义,可以由多个小接口定义组合而成
type ReadWriter interface {
    Reader
    Writer
}
  1. 只依赖于必要功能的最小接口
func StoreData(reader Reader) error {
    ......
}

19.编写好的错误处理

  1. 没有异常机制
  2. error类型实现了error接口
type error interface {
    Error() string
}
  1. 可以通过errors.New来快速创建错误实例
errors.New("")

20.panic

panic vs os.Exit

recover

defer func() {
   if err := recover(); err != nil {
       //恢复错误
   } 
}()

21.package

  1. 基本复用模块单元
    1. 以首字母大写来表明可被包外代码访问
  2. 代码的package可以和所在的目录不一致
  3. 同一目录里的Go代码的package要保持一致
  4. 通过go get来获取远程依赖
    1. go get -u强制从网络更新远程依赖
  5. 注意代码在Github上的组织形式,以适应go get
    1. 直接以代码路径开始,不要有src

22.init方法

23.依赖管理

Go未解决的依赖问题

  1. 同一环境下,不同项目使用同一包的不同版本
  2. 无法管理对包的特定版本的依赖

vendor路径
<p>随着Go1.5 release 版本的发布,vendor目录被添加到除了GOPATH和GOROOT之外的依赖目录查找的解决方案。在Go 1.6之前,你需要手动的设置环境变量</p>

查找依赖包路径的解决方案如下:

  1. 当前包下的vendor目录
  2. 向上级目录查找,直到找到src下的vendor目录
  3. 在GOPATH下面查找依赖包
  4. 在GOROOT目录下查找

常用的依赖管理

三、并发机制

1.Thread vs. Groutine

  1. 创建时默认的stack的大小
    1. JDK5以后Java Thread stack默认为1M
    2. Groutine的Stack初始化大小为2K
  2. 和KSE (kernel Space Entity)的对应关系
    1. Java Thread是1:1
    2. Groutine是M:N

2.Lock

package sync
    Mutex
    RWLock

WaiteGroup

3.CSP并发机制

CSP vs. Actor

4.select

多渠道的选择

select {
    case ret := <- retCh1:
        t.Logf("result %s", ret)
    case ret := <- retCh2:
        t.Logf("result %s", ret)
    default:
        t.Error("No one returned")
}

超时控制

select {
    case ret := <- retCh:
        t.Logf("result %s", ret)
    case <- time.After(time.Second * 1):
        t.Error("time out")
}

5.channel的关闭

6.Context与任务取消

7.单例模式(懒汉式,线程安全)

var once sync.Once
var obj *SingletonObj
func GetSingletonObj() *SingletonObj {
    once.Do(func(){
        fmt.Println("Create Singleton obj.")
        obj = &SingletonObj{}
    })
    return obj
}

8、对象池

9、sync.Pool总结

10、单元测试框架

Benchmark

BDD in Go

项目网站
https://github.com/smartystreets/goconvey

安装
go get -u github.com/smartystreets/goconvey/convey

启动WEB UI
$GOPATH/bin/goconvey

四、其他

1、reflect.TypeOf vs. reflect.ValueOf

2、利用反射编写灵活的代码

reflect.ValueOf(*e).FieldByName("Name")
reflect.ValueOf(e).MethodByName("UpdateAge").Call([]reflect.Value{reflect.ValueOf(1)})

3、架构设计模式:Pipe-Filter模式

4、架构设计模式:Micro Kernel

特点

要点

5、更快的JSON解析

EasyJSON采用代码生成而非反射

6、Http路由规则

7、更好的Router

htttps://github.com/julienschmidt/httprouter

8、性能分析工具

准备工作

通过文件方式输出Profile

9、性能调优

常见分析指标

上一篇 下一篇

猜你喜欢

热点阅读