zoukankan      html  css  js  c++  java
  • 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")
    }
    
    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
    • 数组边界检查
  • 相关阅读:
    PAT 1037. 在霍格沃茨找零钱(20)
    PAT 1036. 跟奥巴马一起编程(15)
    Topcoder SRM633 DIV2 解题报告
    HDU 4565 So Easy! 矩阵快速幂 + 共轭数
    HDU 2256 Problem of Precision 矩阵快速幂 + 共轭数
    FZU 1683 纪念SlingShot 矩阵快速幂
    CodeForces 185A Plant 矩阵快速幂
    HDU 2604 Queuing 矩阵快速幂
    HDU 1575 Tr A 矩阵快速幂
    HDU 1757 A Simple Math Problem 矩阵快速幂
  • 原文地址:https://www.cnblogs.com/52php/p/6350101.html
Copyright © 2011-2022 走看看