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

大道至简,小而蕴真

让事情变得复杂很容易,让事情变得简单才难

深刻的工程文化

优点

  1. 自带gc。
  2. 静态编译,编译好后,扔服务器直接运行。
  3. 简单的思想,没有继承,多态,类等。
  4. 丰富的库和详细的开发文档。
  5. 语法层支持并发,和拥有同步并发的channel类型,使并发开发变得非常方便。
  6. 简洁的语法,提高开发效率,同时提高代码的阅读性和可维护性。
  7. 超级简单的交叉编译,仅需更改环境变量。(花了我两天时间编译一个imagemagick到arm平台)
  8. 内含完善、全面的软件工程工具。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

可视化(原是svg文件,下图为截图):

可视化(原是 svg 文件,下图为截图:

go tool pprof --text http://localhost:6060/debug/pprof/heap

go命令教程

资料

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

http://smallsoho.com/2016/11/20/Go简明教程.html?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 特性简介的更多相关文章

  1. ES6新特性简介

    ES6新特性简介 环境安装 npm install -g babel npm install -g babel-node //提供基于node的REPL环境 //创建 .babelrc 文件 {&qu ...

  2. SpartanBrowser产品和安全特性简介

    v:* { } o:* { } w:* { } .shape { }p.MsoNormal,li.MsoNormal,div.MsoNormal { margin: 0cm; margin-botto ...

  3. AsyncLocal 与 ThreadLocal ThreadStatic特性简介

    AsyncLocal 与 ThreadLocal [.NET深呼吸]基于异步上下文的本地变量(AsyncLocal) https://www.cnblogs.com/tcjiaan/p/5007737 ...

  4. [转帖]sql server版本特性简介、版本介绍简介

    sql server版本特性简介.版本介绍简介 https://www.cnblogs.com/gered/p/10986240.html 目录 1.1.sql server的版本信息 1.2.版本重 ...

  5. haproxy的丰富特性简介

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  6. sql server版本特性简介、版本介绍简介

    1.SQL Server 版本简介 1.1.sql server的版本信息 年    代 版    本 大版本号 1993年 SQL Server for Windows NT 4.21 1994年 ...

  7. ECMAScript 6新特性简介

    目录 简介 ECMAScript和JavaScript的关系 let和const 解构赋值 数组的扩展 函数的扩展 简介 ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言 ...

  8. ECMAScript 2016(ES7)新特性简介

    简介 自从ES6(ECMAScript 2015)在2015年发布以来,ECMAScript以每年一个版本的速度持续向前发展.到现在已经是ECMAScript 2020了. 每个版本都有一些新的特性, ...

  9. ECMAScript 2017(ES8)新特性简介

    目录 简介 Async函数 共享内存和原子操作 Object的新方法 String的新方法 逗号可以添加到函数的参数列表后面了 简介 ES8是ECMA协会在2017年6月发行的一个版本,因为是ECMA ...

随机推荐

  1. RabbitMQ集群下队列存放消息的问题

    RabbitMQ中队列有两种模式 1.默认 Default 2.镜像 Mirror [类似于mongoDB,从一直在通过主的操作日志来进行同步] *如果将队列定义为镜像模式,那么这个队列也将区分主从, ...

  2. PowerDesigner显示Common注释列并自动赋值

    PowerDesigner中默认不显示Common注释列,可根据以下步骤显示并紫东填充Name列内容. 1.显示Common注释列 2.运行VB Script脚本自动赋值 使用Shift+Ctrl+X ...

  3. Jquery ajax json 不执行success的原因 坑爹

    最近在看jQuery的API文档,在使用到jQuery的ajax时,如果指定了dataType为json,老是不执行success回调,而是执行了error回调函数,极度郁闷.后面改为1.2.6版本可 ...

  4. 008_MAC 终端使用技巧

    一.常用终端命令. <1>reset 的作用很简单——将目前「终端」屏幕上的内容清空,就好像刚刚打开终端一样. <2>如果你在一条终端命令中发现有输入错误的话,那么用 cont ...

  5. pwd、ln和重定向命令

    pwd命令 命令功能: ​ 使用pwd命令可以显示当前的工作目录,该命令很简单,直接输入pwd即可,后面不带参数. ​ pwd命令以绝对路径的方式显示用户当前工作目录.命令将当前目录的全路径名称(从根 ...

  6. supervisor安装部署和使用实例

    Supervisord是用Python实现的一款非常实用的进程管理工具,类似于monit,monit和supervisord的一个比较大的差异是supervisord管理的进程必须由superviso ...

  7. ***实用函数:PHP explode()函数用法、切分字符串,作用,将字符串打散成数组

    下面是根据explode()函数写的切分分割字符串的php函数,主要php按开始和结束截取中间数据,很实用 代码如下: <? // ### 切分字符串 #### function jb51net ...

  8. 为K8S集群建立只读权限帐号

    参考URL: https://www.jianshu.com/p/a1a0d64f1245 https://mritd.me/2018/03/20/use-rbac-to-control-kubect ...

  9. checkbox复选框的一些深入研究与理解

    一.一开始的唠叨最近忙于开发,自淫于项目的一步步完工,心浮躁了.舍近而求远,兵家之大忌.我是不是应该着眼于眼前的东西,好好的静下心来,超过一般人的沉静与沉浸,研究最基本的东西呢?这番思考,让我找到了一 ...

  10. ajax和jsonp

    ajax和jsonp 前言:ajax和jsonp可以与后台通信,获取数据和信息,但是又不用刷新整个页面,实现页面的局部刷新. 一.ajax 定义:一种发送http请求与后台进行异步通讯的技术. 原理: ...