Go语言从入门到实战

栏目: Go · 发布时间: 4年前

内容简介:[图片上传失败...(image-8dd3db-1556979504914)]与其他主要编程的差异:类型的预定义值:

一、 Go 语言背景和发展

1.软件开发的新挑战

  • 多核硬件架构
  • 超大规模分布式计算集群
  • Web模式导致的前所未有的开发规模和更新速度

2.Go的三位创始人

  • Rob Pike:Unix的早期开发者,UTF-8创始人
  • Ken Thompson:Unix的创始人,C语言创始人,1983年获图灵奖
  • Robert Griesemer:Google V8 JS Engine开发者,Hot Spot开发者

3.Go语言特点

  • 简单:Go只有25个关键字;特别是对于一些复杂编程任务如:并发编程,内存管理,Go语言有内置的并发支持及GC
  • 高效:Go是编译的静态类型语言,并且可以通过指针进行直接内存访问
  • 生产力:简单清新的依赖管理,简单清新的语法,以及独特的接口类型

二、第一个Go程序

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

1.应用程序入口

  • 必须是main包
  • package main
  • 必须是main方法
  • func main()
  • 文件名不一定是main.go

2.退出返回值

  • Go中main函数不支持任何返回值
  • 通过os.Exit来返回状态

3.获取命令行参数

  • main函数不支持传入参数
  • 在程序中直接通过os.Args获取命令行参数

4.基本数据类型

  • bool
  • string
  • int int8 int16 int32 int64
  • uint uint8 uint16 uint32 uint64
  • byte // alias for uint8
  • rune
  • float32 float64
  • complex64 complex128

与其他主要编程的差异:

  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与工厂模式

  • Map的value可以是一个方法
  • 与Go的Dock type接口方式一起,可以方便的实现单一方法对象的工厂模式

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用于不可以恢复的错误
  • panic退出前会执行defer指定的内容

panic vs os.Exit

  • os.Exit 退出时不会调用defer指定的函数
  • 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方法

  • 在main被执行前,所有依赖的package的init方法都会被执行
  • 不同包的init函数按照包导入的依赖关系决定执行顺序
  • 每个包可以有多个init函数
  • 包的每个源文件也可以有多个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

  • 和Actor的直接通讯不同,CSP模式则是通过Channel进行通讯的,更松耦合一些
  • Go中channel是有容量限制并且独立于处理Groutine,而如Erlang,Actor模式中的mailbox容量是无限的,接受进程也总是被动处理消息

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的关闭

  • 向关闭的channel发送数据,会导致panic
  • v,ok <- ch;ok为bool值,true表示正常接受,false表示通道关闭
  • 所有的channel接受者都会在channel关闭时,立刻从阻塞等待中返回且上述ok值为false。这个广播机制常被利用,进行向多个订阅者同时发送信号。如:退出信号

6.Context与任务取消

  • 根Context:通过context.Background()创建
  • 子Context:context.WithCancel(parentContext)创建
    • ctx,cancel := context.WithCancel(context.Background())
  • 当前Context被取消时,基于他的子context都会被取消
  • 接收取消通知 <- ctx.Done()

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总结

  • 适合于通过复用,降低复杂对象的创建和GC代价
  • 协程安全,会有锁的开销
  • 生命周期受GC影响,不适合于做连接池等,需自己管理生命周期的资源的池化

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

  • reflect.TypeOf 返回类型(reflect.Type)
  • reflect.ValueOf 返回值 (reflect.Value)
  • 可以从reflect.Value获得类型
  • 通过kind的来判断类型

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

  • 按名字访问结构的成员
reflect.ValueOf(*e).FieldByName("Name")
  • 按名字访问结构的方法
reflect.ValueOf(e).MethodByName("UpdateAge").Call([]reflect.Value{reflect.ValueOf(1)})

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

  • 非常适合与数据处理及数据分析系统
  • Filter封装数据处理的功能
  • 松耦合:Filter只跟数据(格式)耦合
  • Pipe用于连接Filter传递数据或者在异步处理过程中缓冲数据流(进程内同步调用,pipe演变为数据在方法调用间传递)

4、架构设计模式:Micro Kernel

特点

  • 易于扩展
  • 错误隔离
  • 保持架构一致性

要点

  • 内核包含公共流程或通用逻辑
  • 将可变或可扩展部分规划为扩展点
  • 抽象扩展点行为,定义接口
  • 利用插件进行扩展

5、更快的JSON解析

EasyJSON采用代码生成而非反射

  • 安装
    go get -u github.com/mailru/easyjson/
  • 使用
    easyjson -all <结构定义>.go

6、Http路由规则

  • URL分为两种,末尾是/:表示一个子树,后面可以跟其他子路径;末尾不是/,表示一个叶子,固定的路径(以/结尾的URL可以匹配它的任何子路径,比如/images会匹配/images/cute-cat.jpg)
  • 它采用最长匹配原则,如果有多个匹配,一定采用匹配路径最长的那个进行处理
  • 如果没有找到任何匹配项,会返回404错误

7、更好的Router

htttps://github.com/julienschmidt/httprouter

8、性能分析工具

准备工作

通过文件方式输出Profile

9、性能调优

常见分析指标

  • Wall Time
  • CPU Time
  • Block Time
  • Memory Time
  • GC times/time spent

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

重构

重构

Martin Fowler / 熊节 / 人民邮电出版社 / 2010 / 69.00元

重构,一言以蔽之,就是在不改变外部行为的前提下,有条不紊地改善代码。多年前,正是本书原版的出版,使重构终于从编程高手们的小圈子走出,成为众多普通程序员日常开发工作中不可或缺的一部分。本书也因此成为与《设计模式》齐名的经典著作,被译为中、德、俄、日等众多语言,在世界范围内畅销不衰。 本书凝聚了软件开发社区专家多年摸索而获得的宝贵经验,拥有不因时光流逝而磨灭的价值。今天,无论是重构本身,业界对重......一起来看看 《重构》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

html转js在线工具
html转js在线工具

html转js在线工具