Go语言入门
1. 简介
的一种BASIC语言.
2. 语言特性
Go语言最主要的特性: 自动垃圾回收
更丰富的内置类型
函数多返回值
错误处理
匿名函数和闭包
类型和接口
并发编程
反射
语言交互性
1.自动垃圾回收
void foo() { char* p = new char[128]; ... // 对p指向的内存块进行赋值 func1(p); // 使用内存指针 delete[] p; }
学过c语言的都知道,当你手动开辟内存空间后,都得delete释放掉该内存。但是每个人都有疏忽的时候,就会造成内存泄露甚至系统崩溃等问题。c++中的空指针,野指针等这些都是手动管理内存的原因,更多内存管理上的问题这里也不多说。
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语言实现了CSP(通信顺序进程, Communicating Sequential Process)模型来作为goroutine间的推荐通信方式。在CSP模型中,一个并发系统由若干并行运行的顺序进程组成,每个进程不能对其他进程的变量赋值。进程之间只能通过一对通信原语实现协作。 Go语言用channel(通道)这个概念来轻巧地实现了CSP模型。 channel的使用方式比较接近Unix系统中的管道( pipe)概念,可以方便地进行跨goroutine的通信。另外,由于一个进程内创建的所有goroutine运行在同一个内存地址空间中,因此如果不同的goroutine不得不去访问共享的内存变量,访问前应该先获取相应的读写锁。 Go语言标准库中的sync包提供了完备的读写锁功能。
下面我们用一个简单的例子来演示goroutine和channel的使用方式。这是一个并行计算的例子,由两个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模块的这个问题,这个功能直接被命名为Cgo。 Cgo既是语言特性,同时也是一个工具的名称。
在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++保持一致,即同时支持以下两种用法:
/* 块注释 */ // 行注释
相信熟悉C和C++的读者也发现了另外一点,即在这段Go示例代码里没有出现分号。 Go程序并不要求开发者在每个语句后面加上分号表示语句结束,这是与C和C++的一个明显不同之处。
有些读者可能会自然地把左花括号{ 另起一行放置,这样做的结果是Go编译器报告编译错误,这点需要特别注意:
syntax error: unexpected semicolon or newline before {
有疑问加站长微信联系(非本文作者)