Golang 特性简介
by sheepbao
主要大概介绍go语言的历史和特性,简单的入门。
来历
很久以前,有一个IT公司,这公司有个传统,允许员工拥有20%自由时间来开发实验性项目。在2007的某一天,公司的几个大牛,正在用c++开发一些比较繁琐但是核心的工作,主要包括庞大的分布式集群,大牛觉得很闹心,后来c++委员会来他们公司演讲,说c++将要添加大概35种新特性。这几个大牛的其中一个人,名为:Rob Pike,听后心中一万个xxx飘过,“c++特性还不够多吗?简化c++应该更有成就感吧”。于是乎,Rob Pike和其他几个大牛讨论了一下,怎么解决这个问题,过了一会,Rob Pike说要不我们自己搞个语言吧,名字叫“go”,非常简短,容易拼写。其他几位大牛就说好啊,然后他们找了块白板,在上面写下希望能有哪些功能(详见文尾)。接下来的时间里,大牛们开心的讨论设计这门语言的特性,经过漫长的岁月,他们决定,以c语言为原型,以及借鉴其他语言的一些特性,来解放程序员,解放自己,然后在2009年,go语言诞生。
思想
Less can be more
大道至简,小而蕴真
让事情变得复杂很容易,让事情变得简单才难
深刻的工程文化
优点
- 自带gc。
- 静态编译,编译好后,扔服务器直接运行。
- 简单的思想,没有继承,多态,类等。
- 丰富的库和详细的开发文档。
- 语法层支持并发,和拥有同步并发的channel类型,使并发开发变得非常方便。
- 简洁的语法,提高开发效率,同时提高代码的阅读性和可维护性。
- 超级简单的交叉编译,仅需更改环境变量。(花了我两天时间编译一个imagemagick到arm平台)
- 内含完善、全面的软件工程工具。Go语言自带的命令和工具相当地强大。通过它们,我们可以很轻松地完成Go语言程序的获取、编译、测试、安装、运行、运行分析等一系列工作,这几乎涉及了开发和维护一个软件的所有环节。
hello
package main func main() {
println("hello, sewise")
}
type
主要讲讲特有的类型,其他基本类型不做介绍
slice
切片:可以理解为动态数组,类似c++的vector 声明一个slice
var slice []T
// 如:
var ints []int
slice的追加
ints = append(ints, 1)
ints = append(ints, 2, 3, 4, 5)
slice的截取
newInts1 := ints[2:3]
newInts2 := ints[2:]
newInts3 := ints[:4]
map
字典:键值对
var json map[string]string
interface
接口:方法的集合,是一种合约 栗子: 声明一个bird接口
var bird interface {
fly()
}
声明一个hen对象(实现bird接口)
type hen struct {
weight int
hasFeather bool
} func (h hen) fly() {
fmt.Println("iI can fly")
} func (h hen) eat() {
h.weight++
fmt.Println("yes, I can eat")
}
声明一个 pig 对象(未实现 bird 接口,因为 pig 不会 fly)
type pig struct {
age int
weignt int
hasFeather bool
} func (p pig) run() {
fmt.Println("I can run")
} func (p pig) eat() {
p.weight += 100
fmt.Println("Yes, I can eat so much")
} func (p pig)sleep(){
fmt.Println("I slept all my life")
} // pig can't fly
channel
通道:轻量集队列,传递某种类型的值的通道
var ch chan int
ch = make(chan int, 1)
往ch写入一个数据
ch<- 8888
从ch读取数据
out := <-ch
特性: channel是有长度的,当channel的缓冲为满时,再往里写入就会阻塞,当channel的缓冲为空时,从channel读就会阻塞
package main import (
"fmt"
"time"
) func main() {
ch := make(chan int)
fmt.Println("ch len:", len(ch))
go func() {
// 往缓冲满的channel里写数据(阻塞)
// ch <- 1
// 从缓冲为空的channel里读数据(阻塞)
<-ch
fmt.Println("I am in minor goroutine")
}()
fmt.Println("I am in main goroutine")
time.Sleep(2 * time.Second)
}
当长度为 0 是,就是不带缓冲的 channel 长度大于0,就是带缓冲的 channel
并发
关键字:go 启动 go 程 一个普通的函数或方法调用前加上关键字 go,即可启动一个 goroutine
go func() {
fmt.Println("start func")
time.Sleep(120*time.Second)
}()
竞争条件检测 -race race.go
package main import (
"fmt"
"time"
) func main() {
a := 1
go func() {
a = 2
}()
a = 3
fmt.Println("a is ", a) time.Sleep(2 * time.Second)
}
检测:执行go run -race race.go
a is 3
==================
WARNING: DATA RACE
Write at 0x00c420072188 by goroutine 6:
main.main.func1()
/Users/bao/program/go/gowork/hello/src/research/race.go:11 +0x3b Previous write at 0x00c420072188 by main goroutine:
main.main()
/Users/bao/program/go/gowork/hello/src/research/race.go:13 +0x9f Goroutine 6 (running) created at:
main.main()
/Users/bao/program/go/gowork/hello/src/research/race.go:12 +0x8e
==================
Found 1 data race(s)
结果分析: goroutine6运行到第11行和main goroutine运行到13行的时候触发竞争了。而且goroutine6是在第12行的时候产生的。
package
包的管理,关键字import,GOPATH
gopath
gopath是一个路径列表,存放go项目工程 GOPATH文件目录结构
├── bin 二进制文件目录
├── pkg 编译好的库文件目录
└── src 源码目录
平常项目的目录结构
├── bin 二进制文件目录
├── pkg 编译好的库文件目录
└── src 源码目录
├── main 入口函数目录
└── vendor 当前项目的库目录
└── sheepbao.com
└── glog
import
比如上面的项目,我要在main.go引入glog包
package main // 引入glog包
import "sheepbao.com/glog" func main() {
glog.Println("test")
}
go的工程工具简介
test
go的命令工具 test,用来做测试
单元测试
go test 只测试函数名被它正确匹配的测试函数 go test -v -run="French|Canal"
栗子: add.go
package test func addOne(i int) int {
return i + 1
}
add_test.go
package test import "testing" func TestAddOne(t *testing.T) {
result := addOne(1)
if result != 2 {
t.Error("1+1!=2")
}
}
bao@baoMac test$ go test -v .
=== RUN TestAddOne
--- PASS: TestAddOne (0.00s)
PASS
ok _/Users/bao/program/go/gowork/hello/src/research/test 0.006s
基准测试
go test -bench=. 内存的分配情况 go test -bench=FuncName -benchmem 栗子: stringsCon.go
package bench import (
"fmt"
) func Sprintf(s1, s2, s3 string) string {
return fmt.Sprintf("%s%s%s", s1, s2, s3)
} func AddString(s1, s2, s3 string) string {
return s1 + s2 + s3
}
stringCon_test.go
package bench import "testing" var (
s1 = "make it run!"
s2 = "make it right!"
s3 = "make it fast!"
) func BenchmarkSprintf(b *testing.B) {
for i := 0; i < b.N; i++ {
Sprintf(s1, s2, s3)
}
} func BenchmarkAddString(b *testing.B) {
for i := 0; i < b.N; i++ {
AddString(s1, s2, s3)
}
}
go test -bench=.
bao@baoMac bench$ go test -bench=.
testing: warning: no tests to run
BenchmarkSprintf-4 5000000 349 ns/op
BenchmarkAddString-4 20000000 61.7 ns/op
PASS
ok _/Users/bao/program/go/gowork/hello/src/research/bench 3.414s
样本测试
package et import (
"fmt"
) func ExampleHello() {
fmt.Println("hello, sewise")
// Output: hello, sewise
}
bao@baoMac example$ go test -v .
=== RUN ExampleHello
--- PASS: ExampleHello (0.00s)
PASS
ok _/Users/bao/program/go/gowork/hello/src/research/example 0.006s
如果把上面的// Output: hello, sewise改为// Output: hello, sewis 则样本测试不能通过
bao@baoMac example$ go test -v .
=== RUN ExampleHello
--- FAIL: ExampleHello (0.00s)
got:
hello, sewise
want:
hello, sewis
FAIL
exit status 1
FAIL _/Users/bao/program/go/gowork/hello/src/research/example 0.006s
pprof
go的命令工具 pprof,用来性能分析(内存使用,泄露和cpu消耗) go tool pprof
- 查看cpu使用: go tool pprof http://localhost:8089/debug/pprof/profile 终端查看:
可视化(原是svg文件,下图为截图):
- 查看内存使用 go tool pprof http://localhost:8089/debug/pprof/heap 终端查看:
可视化(原是 svg 文件,下图为截图:
go tool pprof --text http://localhost:6060/debug/pprof/heap
资料
http://www.csdn.net/article/2012-07-04/2807113-less-is-exponentially-more
http://www.jianshu.com/p/91e40c3e3acb?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io
大牛真身
最大牌的当属B和C语言设计者、Unix和Plan 9创始人、1983年图灵奖获得者Ken Thompson,这份名单中还包括了Unix核心成员Rob Pike(go语言之父)、java HotSpot虚拟机和js v8引擎的开发者Robert Griesemer、Memcached作者Brad Fitzpatrick,等等。
功能
- 规范的语法(不需要符号表来解析)
- 垃圾回收(独有)
- 无头文件
- 明确的依赖
- 无循环依赖
- 常量只能是数字
- int和int32是两种类型
- 字母大小写设置可见性(letter case sets visibility)
- 任何类型(type)都有方法(不是类型)
- 没有子类型继承(不是子类)
- 包级别初始化以及明确的初始化顺序
- 文件被编译到一个包里
- 包package-level globals presented in any order
- 没有数值类型转换(常量起辅助作用)
- 接口隐式实现(没有“implement”声明)
- 嵌入(不会提升到超类)
- 方法按照函数声明(没有特别的位置要求)
- 方法即函数
- 接口只有方法(没有数据)
- 方法通过名字匹配(而非类型)
- 没有构造函数和析构函数
- postincrement(如++i)是状态,不是表达式
- 没有preincrement(i++)和predecrement
- 赋值不是表达式
- 明确赋值和函数调用中的计算顺序(没有“sequence point”)
- 没有指针运算
- 内存一直以零值初始化
- 局部变量取值合法
- 方法中没有“this”
- 分段的堆栈
- 没有静态和其它类型的注释
- 没有模板
- 内建string、slice和map
- 数组边界检查
Golang 特性简介的更多相关文章
- ES6新特性简介
ES6新特性简介 环境安装 npm install -g babel npm install -g babel-node //提供基于node的REPL环境 //创建 .babelrc 文件 {&qu ...
- SpartanBrowser产品和安全特性简介
v:* { } o:* { } w:* { } .shape { }p.MsoNormal,li.MsoNormal,div.MsoNormal { margin: 0cm; margin-botto ...
- AsyncLocal 与 ThreadLocal ThreadStatic特性简介
AsyncLocal 与 ThreadLocal [.NET深呼吸]基于异步上下文的本地变量(AsyncLocal) https://www.cnblogs.com/tcjiaan/p/5007737 ...
- [转帖]sql server版本特性简介、版本介绍简介
sql server版本特性简介.版本介绍简介 https://www.cnblogs.com/gered/p/10986240.html 目录 1.1.sql server的版本信息 1.2.版本重 ...
- haproxy的丰富特性简介
*/ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...
- sql server版本特性简介、版本介绍简介
1.SQL Server 版本简介 1.1.sql server的版本信息 年 代 版 本 大版本号 1993年 SQL Server for Windows NT 4.21 1994年 ...
- ECMAScript 6新特性简介
目录 简介 ECMAScript和JavaScript的关系 let和const 解构赋值 数组的扩展 函数的扩展 简介 ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言 ...
- ECMAScript 2016(ES7)新特性简介
简介 自从ES6(ECMAScript 2015)在2015年发布以来,ECMAScript以每年一个版本的速度持续向前发展.到现在已经是ECMAScript 2020了. 每个版本都有一些新的特性, ...
- ECMAScript 2017(ES8)新特性简介
目录 简介 Async函数 共享内存和原子操作 Object的新方法 String的新方法 逗号可以添加到函数的参数列表后面了 简介 ES8是ECMA协会在2017年6月发行的一个版本,因为是ECMA ...
随机推荐
- [转]Linux联网问题
一.Kali联网问题 首先ifconfig,可以看到没有正在工作的网卡,只有localhost 然后ifconfig -a,可以看到eth0这块网卡并没有离家出走,只是罢工了而已 打开/etc/net ...
- G. (Zero XOR Subset)-less(线性基)
题目链接:http://codeforces.com/contest/1101/problem/G 题目大意:给你n个数,然后让你把这n个数分成尽可能多的集合,要求,每个集合的值看做这个集合所有元素的 ...
- usb的一些网址
一些关于usb的帖子.网址: usb gadget device g_ether.ko 做成usbnetwork http://bbs.csdn.net/topics/370120345 Linux ...
- Daemon函数的用法
Daemon函数的用法 说明: 让一个程序后台运行. 原型: #include <unistd.h> int daemon(int nochdir, int noclose); #incl ...
- Linux硬盘的检测(原创)
http://czmmiao.iteye.com/blog/1058215 概述 随着硬盘容量.速度的快速发展,硬盘的可靠性问题越来越重要,今天的单块硬盘存储容量可轻松达到1TB,硬盘损坏带来的影响非 ...
- ASP.NET结合COM组件发送Email
在开发电子邮件发送程序的时候,我们经常需要使用到相应的组件,其实不需要第三方的组件(例如:Jmail)照常可以做到发送Email的功能. 在系统目录(如c:/winnt或c:/windows)的sys ...
- poj1093
题意:给出一个句子和要求整理后每行包含的字符数,要求将其整理为一种总badness最小的形式.设每个空格长度为n,单个空格的badness计算公式为(n-1)^2.总badness等于所有空格的bad ...
- 使用配置文件启动MongoDB
Ubuntu 16.04 (阿里云ECS),MongoDB 4.0, 原来,已经写了10篇MongoDB的随笔了.可是,自己居然没有使用配置文件启动过MongoDB,对其更多的配置是不明白的. 昨天( ...
- 【前端开发】移动端适配方案js,rem单位转换,640设计稿20px=1rem
! function() { var style = document.createElement("STYLE"), docEl = document.documentEleme ...
- CAS5.2x单点登录(一)——搭建cas服务器
系列文章列表: https://blog.csdn.net/u013825231/article/category/7517313 单点登录的介绍 单点登录(Single Sign On ,简称SSO ...