Go语言学习笔记----(一)初见

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Scrat_Kong/article/details/83215078

Go(golang)

编译型语言已经有(C,C++, Java , C#, Objective-C), 快速业务开发的解释型语言有(PHP, Python,Perl,Ruby,JavaScript,Lua等。)为什么要Go?

众所周知,‘万物源于C’, 2000年后Java逐渐取代C的王者位置,但Java编程体验未尽如人意。Go希望成为互联网时代的C语言。

Go特点:

  1. 并行与分布式
  2. 软件工程的支持
  3. 编程哲学的重塑。

语言简史

贝尔实验室计算科学研究中心,1969年肯汤姆逊,丹尼斯里奇在贝尔实验室的计算科学中心开发出Unix, 还因此衍生出赫赫有名的C语言。20世纪八十年代开始名为Plan9的操作系统研究项目,为了解决Unix中的一些问题,之后几十年中衍生出另一个叫Inferno的项目分支,以及名为Limbo的编程语言。

Limbo用于开发运行在小型计算机上的分布式应用的编程语言,支持模块化编程。编译器和运行时的强类型检查,进程内具有类型的通信通道,原子性垃圾收集和简单的抽象数据类型。即便在没有硬件内存保护的小型设备上也可以安全运行。

Limbo被认为是Go语言的前身。后来贝尔实验室的多次动荡,包括肯汤姆逊本人在内的Plan9项目原班人马加入Google,在Google创造了Go语言。2009年11月Go语言的第一个版本正式对外发布。两年内快速迭代,于2012年3月28日正式发布。

 

语言特性:

Go是一种全新的静态类型开发语言。主要特性如下

  • 自动垃圾回收:

C语言中,如果开发者疏忽没有释放内存,那么就会引发经典而且恼人的内存泄漏问题。而且手动管理内存的另一个问题就是到处传递的指针无法确定释放指针所指向的内存块。假如代码中某个位置释放了内存,而其他地方还在用这块内存的指针,那么这些指针就会成为野指针或者悬空指针,对这些指针进行任何读写操作都会造成不可预料的后果。

到目前为止,垃圾泄露的最佳解决方案是在语言级别引入自动垃圾回收算法。所谓垃圾回收,就是所有内存分配动作都会被在运行时记录,同时任何对该内存的使用也会被记录,然后垃圾回收器就会对已经分配的内存进行跟踪检测,一旦发现有些内存不再被任何人使用,就阶段性回收这些没人用的内存。(当然,要尽量小化垃圾回收的性能损耗)

  • 丰富的内置类型

整型,浮点型,数组,字符串,字典。

数组切片(slice):可动态增长的数组。

  • 函数多返回值:

Python外的其他语言都不支持多返回值,Go语言也对其予以支持。

func getName()(firstName, middleName, lastName, nickName string){
     return "May", "M", "Chen", "Babe"
}

而且,并不是每个返回值都要赋值,没有明确赋值的可以返回值保持空值。函数的调用也比C/C++简化很多。

fn, mn, ln, nn := getName()  # 类似Python的拆包

_, _, lastName, _ := getName()  # 避免声明完全没有用的变量
  • 错误处理

go语言引入三个关键字用于标准的错误处理流程。 三个关键字分别是defer、panic和 recover。

go语言的错误机制可以大大减少代码量,让开发者无序仅仅为了程序安全性而大量添加一层层的try-catch语句。

  • 匿名函数与闭包

go语言中函数也是值类型,可以当做参数进行传递,支持常规的匿名函数和闭包。

# 名为f的匿名函数  开发者可以随意对该匿名函数变量进行传递与调用
f := func(x, y int) int{
     return x + y
}
  • 类型与接口

go语言类型的定义非常接近C语言中的结构struct, 直接沿用了struct关键字,不过go不支持继承与重载。只是支持了基本的类型组合功能。

go语言不只是简单的面向对象的减法,还引入了非常强大的非侵入式接口的概念。让开发者从C++和Java卡法中的接口管理中解脱出来。

  • 并发编程

go语言引入goroutine概念,它使得并发编程变得简单,通过使用goroutine而不是裸用操作系统的并发机制,以及使用消息传递来共享内存而不是使用共享内存来通信。

goroutine是一种比线程更轻盈、省资源的协程。通过在函数调用前使用关键字go, 可以让函数以goroutine方式执行。

go语言通过系统的线程来多路派遣这些函数执行,使得每个用go关键字执行的函数可以运行为一个单位协程。当一个协程阻塞的时候,调度器自动把其他协程安排到另外的线程中去执行,从而实现了程序无等待并行化运行。而且调度的开销非常小,一颗CPU调度的规模不下每秒百万次,我们得以创建大量的goroutine,从而很轻松的编写高并发程序,以达到我们的目的。

go语言实现了CSP(通信顺序进程)模型来作为goroutine间的推荐通信方式。在CSP模型中,一个并发系统由若干并行的顺序进程组成,每个进程能对其他进程的变量赋值,进程之间只能通过一对通信原语实现协作。go语言使用channel(通道)来轻巧实现CSP模型。 channel比较接近Unix系统中的pipe概念,可以方便的进行跨goroutine通信。

一个进程内创建的所有goroutine运行在同一个内存地址空间中,因此如果不同的goroutine不得不去访问共享的内存变量。访问前应该先获取相应的读写锁。go语言标准库sync包提供了完备的读写锁功能。

下面是一个使用goroutine和channel进行并行计算的例子,由两个goroutine进行并行累加计算。

package main

import "fmt"

func sum(values[]  int, resultChan chan int){
     sum := 0
     for _, value := range values{
            sum += value
     }
     resultChan <- sum  // 将计算结果发送到channel中
}

func  main(){
      values := [] int{ 1,2,3,4,5,6,7,8,9,10}
      resultChan := make(chan int , 2)
      go sum(values[:len(values)/2], resultChan)
      go sum(values[len(values)/2:], resultChan)
      sum1, sum2 := <-resultChan, <-resultChan  // 接受结果
      
      fmt.PrintIn("Result:", sum1, sum2, sum1+sum2)
}
  • 反射

反射是在Java出现后迅速流行起来的概念,通过反射,可以获取对象类型的详细信息,并可动态操作对象。缺点是可读性不强,若非必要,不建议使用反射。

go语言的反射实现了反射的大部分功能,但是没有想Java那样内置类型工厂,无法像Java那样通过类型字符串创建对象实例。

反射最常见的应用场景是做对象的序列化, go语言的标准库的encoding/json, encoding/xml, encoding/gob, encoding/binary等包都大量依赖反射功能实现。

  • 语言交互性

由于go语言与C语言的天生联系,go语言会重用现有C模块, 这个功能直接命名为Cgo, Cgo既是语言特性,也是工具名称。

go代码中,可以使用Cgo特定语法混合编写C代码。

具体用法会在后续笔记中详细解释。

猜你喜欢

转载自blog.csdn.net/Scrat_Kong/article/details/83215078