GO语言基础入门一

Go语言入门

1. 简介

Go语言是谷歌推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发Go,是因为过去10多年间软件开发的难度令人沮丧。
Go是谷歌2009发布的第二款编程语言。2009年7月份,谷歌曾发布了Simple语言,它是用来开发Android应用
的一种BASIC语言.
北京时间2010年1月10日,Go语言摘得了TIOBE公布的2009年年度大奖。该奖项授予在2009年市场份额增长最多的编程语言。
谷歌资深软件工程师罗布·派克(Rob Pike)表示,“Go让我体验到了从未有过的开发效率。”派克表示,今天的C++或C一样,Go是一种系统语言。他解释道,“使用它可以进行快速开发,同时它还是一个真正的编译语言,我们之所以现在将其开源,原因是我们认为它已经非常有用和强大。”
2007年,谷歌把Go作为一个20%项目开始研发,即让员工抽出本职工作之外时间的20%, 投入在该项目上。除了派克外,该项目的成员还有其他谷歌工程师也参与研发。
派克表示,编译后Go代码的运行速度与C语言非常接近,而且编译速度非常快,就像在使用一个交互式语言。现有编程语言均未专门对多核处理器进行优化。Go就是谷歌工程师为这类程序编写的一种语言。它不是针对编程初学者设计的,但学习使用它也不是非常困难。Go支持面向对象,而且具有真正的闭包(closures)和反射 (reflection)等功能。
在学习曲线方面,派克认为Go与Java类似,对于Java开发者来说,应该能够轻松学会 Go。之所以将Go作为一个开源项目发布,目的是让开源社区有机会创建更好的工具来使用该语言,例如 Eclipse IDE中的插件
谷歌公开发布的所有网络应用中,均没有使用Go,但是谷歌已经使用该语言开发了几个内部项目。派克表示,Go是否会对谷歌即将推出的Chrome OS产生影响,还言之尚早,不过Go的确可以和Native Client配合使用。他表示“Go可以让应用完美的运行在浏览器内。”例如,使用Go可以更高效的实现Wave,无论是在前端还是后台。
Go 同时具有两种编译器,一种是建立在GCC基础上的Gccgo,另外一种是分别针对64位x64和32位x86计算机的一套编译器(6g和8g)。谷歌目前正在研发其对ARM芯片和Android设备的支持。派克表示,“Android手机存在的问题是,我们一直没有一个数学协处理器。”

2. 语言特性

Go语言最主要的特性:
自动垃圾回收
更丰富的内置类型
函数多返回值
错误处理
匿名函数和闭包
类型和接口
并发编程
反射
语言交互性

1.自动垃圾回收

void foo()
{
char* p = new char[128];
... // 对p指向的内存块进行赋值
func1(p); // 使用内存指针
delete[] p;
}

学过c语言的都知道,当你手动开辟内存空间后,都得delete释放掉该内存。但是每个人都有疏忽的时候,就会造成内存泄露甚至系统崩溃等问题。c++中的空指针,野指针等这些都是手动管理内存的原因,更多内存管理上的问题这里也不多说。

GO语言做为一门新语言,较c++没有“强大”的指针功能,因此可以很自然的包含垃圾回收机制。系统自己帮我们判断是否释放之前分配的内存。

2.丰富的内置类型

GO语言内置了新语言中内置的高级类型。

例如:

map

数字切片Slice:与vector相似,可以认为是一种可动态增长的数组

3.函数多返回值

GO语言支持多返回值,这相对于其他语言有所区别

func getName()(firstName, middleName, lastName, nickName s t r i n g){
 return "May", "M", "Chen", "Babe"
}
因为返回值都已经有名字,因此各个返回值也可以用如下方式来在不同的位置进行赋值,从而提供了极大的灵活性

func getName()(firstName, middleName, lastName, nickName s t r i n g){
 firstName = "May"
 middleName = "M"
 lastName = "Chen"
 nickName = "Babe"
 return
}

我们调用函数时

fn, mn, ln, nn := getName()

返回的参数会一一对应进行赋值。如果有些参数不需要,可用_进行忽略

_, _, lastName, _ := getName()

3.错误处理

Go语言引入了 3个关键字用于标准的错误处理流程,这3个关键字分别为defer、 panic和recover。

Go语言的错误处理机制可以大量减少代码量

4.匿名函数和闭包

在GO语言中,所有得函数也是值类型,可以作为参数进行传递,这和lua脚本相似

GO语言支持匿名函数和闭包,下面定义了一个名为f的匿名函数,开发者可以随意对该匿名函数变量进行传递和调用

f := func(x, y i n t) i n t {
 return x + y
}
我们在实现Bird类型时完全没有任何IFly的信息。我们可以在另外一个地方定义这个IFly
接口:
type IFly interface {
  Fly()
}
这两者目前看起来完全没有关系,现在看看我们如何使用它们:
func main() {
  var fly IFly = new(Bird)
  fly.Fly()
}

可以看出,虽然Bird类型实现的时候,没有声明与接口 IFly的关系,但接口和类型可以直接转换,甚至接口的定义都不用在类型定义之前,这种比较松散的对应关系可以大幅降低因为接口调整而导致的大量代码调整工作。

5.并发编程

Go语言引入了goroutine概念,它使得并发编程变得非常简单。通过使用goroutine而不是裸用操作系统的并发机制,以及使用消息传递来共享内存而不是使用共享内存来通信, Go语言让并发编程变得更加轻盈和安全。


通过在函数调用前使用关键字go,我们即可让该函数以goroutine方式执行。 goroutine是一种比线程更加轻盈、更省资源的协程。 Go语言通过系统的线程来多路派遣这些函数的执行,使得每个用go关键字执行的函数可以运行成为一个单位协程。当一个协程阻塞的时候,调度器就会自动把其他协程安排到另外的线程中去执行,从而实现了程序无等待并行化运行。而且调度的开销非常小,一颗CPU调度的规模不下于每秒百万次,这使得我们能够创建大量的goroutine,从而可以很轻松地编写高并发程序,达到我们想要的目的。

Go语言实现了CSP(通信顺序进程, Communicating Sequential Process)模型来作为goroutine间的推荐通信方式。在CSP模型中,一个并发系统由若干并行运行的顺序进程组成,每个进程不能对其他进程的变量赋值。进程之间只能通过一对通信原语实现协作。 Go语言用channel(通道)这个概念来轻巧地实现了CSP模型。 channel的使用方式比较接近Unix系统中的管道( pipe)概念,可以方便地进行跨goroutine的通信。另外,由于一个进程内创建的所有goroutine运行在同一个内存地址空间中,因此如果不同的goroutine不得不去访问共享的内存变量,访问前应该先获取相应的读写锁。 Go语言标准库中的sync包提供了完备的读写锁功能。

下面我们用一个简单的例子来演示goroutinechannel的使用方式。这是一个并行计算的例子,由两个goroutine进行并行的累加计算,待这两个计算过程都完成后打印计算结果
<pre name="code" class="cpp">func 
 Name string
 LifeExpectance int
}
func (b *Bird) Fly() {
 fmt.Println("I am flying...")
}
func main() {
 sparrow := &Bird{"Sparrow", 3}
 s := reflect.ValueOf(sparrow).Elem()
 typeOfT := s.Type()
 for i := 0; i < s.NumField(); i++ {
 f := s.Field(i)
 fmt.Printf("%d: %s %s = %v\n", i, typeOfT.Field(i).Name, f.Type(),
 f.Interface())
 }
}
该程序的输出结果为:
0: Name string = Sparrow
1: LifeExpectance int = 3



6.语言交互

由于Go语言与C语言之间的天生联系, Go语言的设计者们自然不会忽略如何重用现有C模块的这个问题,这个功能直接被命名为CgoCgo既是语言特性,同时也是一个工具的名称。

Go代码中,可以按Cgo的特定语法混合编写C语言代码,然后Cgo工具可以将这些混合的C代码提取并生成对于C功能的调用包装代码。开发者基本上可以完全忽略这个Go语言和C语言的边界是如何跨越的。

Java中的JNI不同, Cgo的用法非常简单,比如代码清单1-3就可以实现在Go中调用C语言标准库的puts函数。

package main
/*
#include <stdio.h>
*/
import "C"
import "unsafe"
func main() {
 cstr := C.CString("Hello, world")
 C.puts(cstr)
 C.free(unsafe.Pointer(cstr))
}

Go程序的代码注释与C++保持一致,即同时支持以下两种用法:

/*
块注释
*/
// 行注释

相信熟悉CC++的读者也发现了另外一点,即在这段Go示例代码里没有出现分号。 Go程序并不要求开发者在每个语句后面加上分号表示语句结束,这是与CC++的一个明显不同之处。
有些读者可能会自然地把左花括号{ 另起一行放置,这样做的结果是Go编译器报告编译错误,这点需要特别注意:
syntax error: unexpected semicolon or newline before {







本文来自:CSDN博客

感谢作者:chenqijing2

查看原文:GO语言基础入门一

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。