golang 特性简介
sheepbao·2017-01-22 08:37:28·552次阅读·发布于 Go问答

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

大道至简,小而蕴真

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

深刻的工程文化

优点

  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") } type 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

包的管理,关键字importGOPATH

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 终端查看: image_1b72f0lh9tir1prf1r2012codlt13.png-164.9kB

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

image_1b72f233avto14d7on4h3nlm51g.png-129.8kB * 查看内存使用 go tool pprof http://localhost:8089/debug/pprof/heap 终端查看: image_1b72elqek180t8b315kn20hhlr9.png-177.3kB

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

image_1b72euk7b1knr1d1n1ugq2pe19kim.png-176.7kB

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
  • 数组边界检查
发起回帖
未登录,登录后可以回帖