惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

www.infosecurity-magazine.com
www.infosecurity-magazine.com
D
DataBreaches.Net
T
Tailwind CSS Blog
M
MIT News - Artificial intelligence
Stack Overflow Blog
Stack Overflow Blog
F
Full Disclosure
V2EX - 技术
V2EX - 技术
N
News and Events Feed by Topic
Help Net Security
Help Net Security
L
LangChain Blog
Y
Y Combinator Blog
宝玉的分享
宝玉的分享
Google Online Security Blog
Google Online Security Blog
P
Proofpoint News Feed
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
The Blog of Author Tim Ferriss
Google DeepMind News
Google DeepMind News
The Register - Security
The Register - Security
B
Blog RSS Feed
N
Netflix TechBlog - Medium
N
News | PayPal Newsroom
TaoSecurity Blog
TaoSecurity Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
V
Vulnerabilities – Threatpost
B
Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
I
Intezer
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园_首页
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
AI
AI
aimingoo的专栏
aimingoo的专栏
大猫的无限游戏
大猫的无限游戏
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Cyberwarzone
Cyberwarzone
P
Proofpoint News Feed
Google DeepMind News
Google DeepMind News
G
GRAHAM CLULEY
Vercel News
Vercel News
罗磊的独立博客
MyScale Blog
MyScale Blog
Last Week in AI
Last Week in AI
博客园 - 司徒正美
C
CERT Recently Published Vulnerability Notes
GbyAI
GbyAI
Scott Helme
Scott Helme
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
T
Troy Hunt's Blog
A
About on SuperTechFans
P
Privacy International News Feed

极客兔兔

Go sync.Cond | Go 语言高性能编程 Go 死码消除与调试(debug)模式 | Go 语言高性能编程 Go sync.Once | Go 语言高性能编程 Go 逃逸分析 | Go 语言高性能编程 2020 年终总结 | 极客兔兔 Go struct 内存对齐 | Go 语言高性能编程 Go 空结构体 struct{} 的使用 | Go 语言高性能编程 控制协程(goroutine)的并发数量 | Go 语言高性能编程 | 极客兔兔 如何退出协程 goroutine (其他场景) | Go 语言高性能编程 如何退出协程 goroutine (超时场景) | Go 语言高性能编程 Go 语言陷阱 - 数组和切片 | Go 语言高性能编程 减小 Go 代码编译后的二进制体积 | Go 语言高性能编程 Go Reflect 提高反射性能 | Go 语言高性能编程 读写锁和互斥锁的性能比较 | Go 语言高性能编程 | 极客兔兔 for 和 range 的性能比较 | Go 语言高性能编程 切片(slice)性能及陷阱 | Go 语言高性能编程 | 极客兔兔 字符串拼接性能及原理 | Go 语言高性能编程 | 极客兔兔 pprof 性能分析 | Go 语言高性能编程 benchmark 基准测试 | Go 语言高性能编程 Go 语言高性能编程 | 极客兔兔 Go 接口型函数的使用场景 | 极客兔兔 Python 简明教程 | 快速入门 | 极客兔兔 Go 语言笔试面试题(代码输出) | 极客面试 | 极客兔兔 动手写RPC框架 - GeeRPC第七天 服务发现与注册中心(registry) | 极客兔兔 动手写RPC框架 - GeeRPC第六天 负载均衡(load balance) 动手写RPC框架 - GeeRPC第五天 支持HTTP协议 | 极客兔兔 动手写RPC框架 - GeeRPC第四天 超时处理(timeout) | 极客兔兔 动手写RPC框架 - GeeRPC第三天 服务注册(service register) 动手写RPC框架 - GeeRPC第二天 支持并发与异步的客户端 | 极客兔兔 动手写RPC框架 - GeeRPC第一天 服务端与消息编码 | 极客兔兔 7天用Go从零实现RPC框架GeeRPC | 极客兔兔 Go 语言笔试面试题(并发编程) | 极客面试 | 极客兔兔 Go 语言笔试面试题(基础语法) | 极客面试 | 极客兔兔 Go 语言笔试面试题汇总 | 极客面试 | 极客兔兔 Go Context 并发编程简明教程 | 快速入门 Go Mmap 文件内存映射简明教程 | 快速入门 动手写ORM框架 - GeeORM第七天 数据库迁移(Migrate) | 极客兔兔 动手写ORM框架 - GeeORM第六天 支持事务(Transaction) | 极客兔兔 动手写ORM框架 - GeeORM第五天 实现钩子(Hooks) | 极客兔兔 动手写ORM框架 - GeeORM第四天 链式操作与更新删除 | 极客兔兔 动手写ORM框架 - GeeORM第三天 记录新增和查询 | 极客兔兔 动手写ORM框架 - GeeORM第二天 对象表结构映射 | 极客兔兔 动手写ORM框架 - GeeORM第一天 database/sql 基础 SQLite 常用命令 | 速查表(Cheat Sheet) 7天用Go从零实现ORM框架GeeORM | 极客兔兔 动手写分布式缓存 - GeeCache第七天 使用 Protobuf 通信 动手写分布式缓存 - GeeCache第六天 防止缓存击穿 | 极客兔兔 动手写分布式缓存 - GeeCache第五天 分布式节点 | 极客兔兔 动手写分布式缓存 - GeeCache第四天 一致性哈希(hash) | 极客兔兔 Go Mock (gomock)简明教程 | 快速入门 动手写分布式缓存 - GeeCache第三天 HTTP 服务端 动手写分布式缓存 - GeeCache第二天 单机并发缓存 | 极客兔兔 Go Test 单元测试简明教程 | 快速入门 7天用Go从零实现分布式缓存GeeCache | 极客兔兔 Go WebAssembly (Wasm) 简明教程 | 快速入门 Go RPC & TLS 鉴权简明教程 | 快速入门 Go Protobuf 简明教程 | 快速入门 Go语言动手写Web框架 - Gee第七天 错误恢复(Panic Recover) WSL, Git, Mircosoft Terminal 等常用工具配置 Rust 简明教程 | 快速入门 | 极客兔兔 Go语言动手写Web框架 - Gee第六天 模板(HTML Template) 百宝箱 - 值得收藏的工具网站 | 极客兔兔 Go语言动手写Web框架 - Gee第五天 中间件Middleware | 极客兔兔 Go语言动手写Web框架 - Gee第四天 分组控制Group | 极客兔兔 Go语言动手写Web框架 - Gee第三天 前缀树路由Router | 极客兔兔 博客折腾记(七) - Gitalk Plus | 极客兔兔 Go语言动手写Web框架 - Gee第二天 上下文Context | 极客兔兔 博客折腾记(六) - 不要为了流量忘记了初心 | 极客兔兔 Go语言动手写Web框架 - Gee第一天 http.Handler | 极客兔兔 7天用Go从零实现Web框架Gee教程 | 极客兔兔 Go Gin 简明教程 | 快速入门 Go 语言简明教程 | 快速入门 | 极客兔兔 机器学习笔试面试题 11-20 | 极客面试 | 极客兔兔 机器学习笔试面试题 1-10 | 极客面试 | 极客兔兔 机器学习笔试面试题汇总 | 极客面试 | 极客兔兔 TensorFlow 2 中文文档 - RNN LSTM 文本分类 TensorFlow 2 中文文档 - TFHub 迁移学习 TensorFlow 2 中文文档 - 卷积神经网络分类 CIFAR-10 TensorFlow 2 中文文档 - 保存与加载模型 TensorFlow 2 中文文档 - 过拟合与欠拟合 TensorFlow 2 中文文档 - 回归预测燃油效率 TensorFlow 2 中文文档 - 特征工程结构化数据分类 TensorFlow 2 中文文档 - IMDB 文本分类 TensorFlow 2 中文文档 - MNIST 图像分类 TensorFlow 2 / 2.0 中文文档 TensorFlow 2.0 (九) - 强化学习 70行代码实战 Policy Gradient 博客折腾记(五) - 友链这件事,没那么简单 | 极客兔兔 博客折腾记(四) - 原创资格是争取来的 | 极客兔兔 TensorFlow 2.0 (八) - 强化学习 DQN 玩转 gym Mountain Car TensorFlow 2.0 (七) - 强化学习 Q-Learning 玩转 OpenAI gym 博客折腾记(三) - 主题设计、彩蛋与阅读量翻倍 | 极客兔兔 TensorFlow 2.0 (六) - 监督学习玩转 OpenAI gym game 博客折腾记(二) - 对搜索引擎的理解 | 极客兔兔 博客折腾记(一) - 极致性能的尝试 | 极客兔兔 Pandas 数据处理(三) - Cheat Sheet 中文版 TensorFlow 2.0 (五) - mnist手写数字识别(CNN卷积神经网络) TensorFlow入门(四) - mnist手写数字识别(制作h5py训练集) | 极客兔兔 TensorFlow入门(三) - mnist手写数字识别(可视化训练) | 极客兔兔 Pandas 数据处理(二) - 筛选数据 | 极客兔兔 Pandas 数据处理(一) - DataFrame 与 Series
Go2 新特性简明教程 | 快速入门 | 极客兔兔
2019-08-15 · via 极客兔兔

quick-go2

图片引用自udemy.com

Go 的演进

Go语言/golang 诞生于2007年,经过12年的发展,Go逐渐成为了云计算领域新一代的开发语言。Go语言在牺牲很少性能的情况下,语法简洁,功能强大。我是Python的重度用户,在学习Go时,却有一种在学习Python的感觉。并非语法相似,而是Go语言作为一门编译型语言,竟然能够像Python一样,少量的代码就能够完成尽可能多的事情。Go语言仿佛是C和Python的结合体。

Go是如何火起来的呢?我觉得有几个主要的原因,除了语言本身性能好,语法简单,易上手外。Go语言原生支持GoroutineChannel,极大地降低了并发和异步编程的复杂度。对于服务端编程,并发和异步尤其重要,相比之下,C++,Java等语言的并发和异步控制逻辑过于复杂。另外,杀手级应用Docker的出现起到了很大的推动作用。

Go语言也有很多令人诟病的地方,例如包管理机制,Go直到v1.6才默认开启了vendor机制,vendor机制非常简陋,简单说就是在项目目录下增加一个vendor文件夹,里面放第三方依赖。vendor机制是没有版本概念的,而且不能解决vendor目录嵌套的问题以及同名包函数冲突问题。后来社区涌现了大量的包管理工具,仅官方推荐的包管理工具就有15种之多,应用比较广泛的,如dep、govendor。直到v1.11,官方增加了Go modules机制,才算较为完整地解决了包管理的问题。

Go2 可以说是Go语言一个非常重要的里程碑,Go1 目前虽然已经到了1.12版本,事实上每一个版本很少涉及语法层面的变化,而且每个版本都是向前兼容的。较大的改动如下:

  • Go1.2 切片操作
1
2
var a = make([]int, 10)
var b = a[i:j:k]
  • Go1.4 for语言加强
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

for i, v := range x {

}

for i := range x {

}


var times [5][0]int

for i := 0; i < len(times); i++ {

}

for _ = range times {

}
  • Go1.9 类型别名
1
type T1 = T2

Go 2 设计草案

为了进一步完善Go语言,提供更好的体验。Go语言社区目前发布了三类重要的设计草案,分别是错误处理(Error handling)错误值(Error values)泛型(Generics),这几个草案代表了社区重点关注的完善方向,但并不代表最终的实现。

错误处理(Error Handling)

Go1 的错误处理机制非常简单,通过返回值的方式,强迫调用者对错误进行处理,这种设计导致会在代码中写大量的if判断。例如:

1
2
3
4
5
6
7
8
func CopyFile(src, dst string) {
r := os.Open(src)
defer r.Close()

w := os.Create(dst)
io.Copy(w, r)
w.Close()
}

IO操作容易引发错误,文件打开失败,创建失败,拷贝失败等都会产生错误。如果要对这个函数进行完整的错误处理,代码将变成这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
func CopyFile(src, dst string) error {
r, err := os.Open(src)
if err != nil {
return err
}
defer r.Close()

w, err := os.Create(dst)
if err != nil {
return err
}
defer w.Close()

if _, err := io.Copy(w, r); err != nil {
return err
}
if err := w.Close(); err != nil {
return err
}
}

看似逻辑清晰,但不够优雅,充斥了大量重复的逻辑。这是Go错误处理机制的缺陷。同时,因为错误处理机制的繁琐,很多开发者在开发应用时,很少去检查并处理错误,程序的健壮性得不到保证。

为了解决这个问题,Go2 发布了一个设计草案供社区讨论,Go2将会完善错误处理机制,错误处理的语法将会简洁很多。

这个提案引入了handle errcheck关键字,上面的函数可以简化成:

1
2
3
4
5
6
7
8
9
10
11
func CopyFile(src, dst string) error {
handle err {
return fmt.Errorf("copy %s %s: %v", src, dst, err)
}
r := check os.Open(src)
defer r.Close()

w := check os.Create(dst)
check io.Copy(w, r)
check w.Close()
}

为什么不使用被Java、Python等语言采用的try关键字呢?比如写成:

1
data := try parseHexdump(string(hex))

上面的写法看似和谐,但try关键字直接应用在 error values 时,可读性就没那么好了:

1
2
3
4
5
data, err := parseHexdump(string(hex))
if err == ErrBadHex {
... special handling ...
}
try err

很明显,在这种场景下,check err显然比try err更有意义。

错误值(Error values)

同样由于错误处理机制设计得较为简陋,Go语言对Error values支持有限。任何值,只要实现了error接口,都是错误类型。由于缺少细粒度的设计,在各种库当中,判断是否产生错误以及产生了哪类错误的方式多种多样,例如io.EOFos.IsNotExisterr.Error()等,。另外,Go语言目前没有机制追溯到完整的错误链条。例如,

1
2
3
4
5
6
7
8
9
10
11
func funcB() error {
if v, err := funcA(); if err != nil {
return fmt.Errorf("connect to db: %v", err)
}
}
func funcC() error {
v, err := funcB()
if err != nil {
return fmt.Errorf("write users database: %v", err)
}
}

funcC返回的错误信息是:

1
write users database: connect to db: open /etc/xx.conf: permission denied

每一层,用额外的字符串对错误进行封装,是目前最常用的方法,除了通过字符串解析,很难还原出完整的错误链条。

为了解决Error values缺少标准的问题,有2个提案,分别针对Error inspectionError formatting

  • 针对 Error inspection ,为error定义了一个可选的接口Unwrap,用来返回错误链上的下一个错误。
1
2
3
4
5
package errors

type Wrapper interface {
Unwrap() error
}

例如,

1
2

func (e *WriteError) Unwrap() error { return e.Err }
  • 针对 Error format,定义了一个可选的接口Format,用来返回错误信息。
1
2
3
4
5
package errors

type Formatter interface {
Format(p Printer) (next error)
}

例如,

1
2
3
4
5
6
7
func (e *WriteError) Format(p errors.Printer) (next error) {
p.Printf("write %s database", e.Database)
if p.Detail() {
p.Printf("more detail here")
}
return e.Err
}

泛型(Generics)

Go语言当前可使用inferface{},允许函数参数和返回值是任何类型的值。但这过于灵活,很多时候需要在获取参数后使用类型断言,进而决定下一步的处理。对比C++/Java的标准容器,Go语言在泛型方面有很大不足,因此针对泛型的提案即希望弥补这方面的不足。提案希望能够支持以下功能:

1
2
3
4
5
6
7
8
9
type List(type T) []T

func Keys(type K, V)(m map[K]V) []K

func Uniq(<-chan T) <-chan T

func Merge(chans ...<-chan T) <-chan T

func SortSlice(data []T, less func(x, y T) bool)

例如,我们需要返回一个map对象中所有的键,而希望这个键的类型可以是任意类型。

1
2
3
4
var ints List(int)
keysA := Keys(int, string)(map[int]string{1:"one", 2: "two"})
keysB := Keys(string, string)(map[string]string{"name":"geektutu", "age": "twenty"})

参考:Go2 wiki - Github

Go 2 新特性

Go2还未正式发布,发布后更新



上一篇 « 博客折腾记(六) - 不要为了流量忘记了初心 下一篇 » Go语言动手写Web框架 - Gee第二天 上下文Context