目录为什么我们需要Go语言1Go语言的简介2面向对象编程4Go语言语法32并发编程5一、为什么我们需要Go语言为什么我们需要Go语言4是什么促使Go的出现随着机器性能的提升、软件规模与复杂度的提高,Java逐步取代了单机时代的编程之王C语言的位置。然后Java编程的体验并未尽如人意。历年来的编程语言排行榜显示,Java语言的市场份额在逐步下跌。Go语言此时应运而生,Go语言官方自称Go语言的出现是因为“近10年来开发程序之难让我们有点沮丧”。Go希望成为互联网时代的C语言。为什么我们需要Go语言5互联网时代的C语言需要考虑哪些关键问题呢并行与分布式支持多核化和集群化是互联网时代的典型特征。软件工程支持互联网时代C语言需要考虑软件品质保障和团队协作相关的话题编程哲学的重塑互联网时代C语言需要回答什么才是最佳的编程实践这个问题。为什么我们需要Go语言6Go语言的在这些问题上的处理并行与分布式支持•并发执行的“执行体”。Go语言在语言级别支持协程(微线程)。多数语言在语法层面并不直接支持协程,而通过库的方式支持协程的功能也不完整。•执行体间的互斥和同步。Go语言提供协程之间的互斥和同步。•执行体间的消息传递。多数语言在并发编程模型上选择了共享内存模型,而Go语言选择了消息队列模型。软件工程支持Go语言可能是第一个将代码风格强制统一的语言。编程哲学的重塑Go语言用批判吸收的眼光,融合众家之长,但时刻警惕特性复杂化,极力维持语言特性的简洁,力求小而精。•Go语言反对函数和操作符重载•Go语言放弃构造和析构函数•Go语言支持类、类成员方法、类的组合,但反对继承,反对虚函数和虚函数重载为什么我们需要Go语言7Go语言的目标提升现有编程语言对程序库等依赖性(dependency)的管理。解决多处理器的任务Go语言的特色简洁、快速、安全、并行、有趣、开源、支持泛型编程、内存管理、数组安全、编译迅速。二、Go语言的简介Go语言的简介9Go语言简史Go语言是由贝尔实验室包括肯·汤普森在内的Plan9原班人马开发。Go语言的第一个版本在2009年11月正式对外发布,并在此后的两年内快速迭代,发展迅猛。第一个正式版本在2012年3月28正式发布。Go语言的简介10Go语言特性自动垃圾回收更丰富的内置类型函数多返回值错误处理匿名函数和闭包类型和接口并发编程反射语言交互性三、Go语言语法Go语言语法12变量变量声明varv1intvarv2stringvarv3[10]intvar(v1intv2string)变量初始化varv1int=10//okvarv2=10//okv3:=10//okv2:=10//errorGo语言语法13变量变量赋值varv1intv1=123i,j=j,i//多重赋值,交换匿名变量funcGetName()(firstName,lastName,nickNamestring){return“May”,“Chan”,“ChibiMaruko”}_,_,nickName:=GetName()//仅获取nickName,_为匿名变量占位符Go语言语法14常量字面常量常量定义预定义常量const(//iota重置为0c0=iota//c0为0c1=iota//c1为1c2=iota//c2为2)枚举const(Sunday=iotaMondaynumberDays//这个常量未导出)Go语言预定义了true,false,iotaGo语言语法15类型基础类型布尔类型bool整型int8byteint16intuintuintptr浮点类型float32float64复数类型complex64complex128字符串string字符类型rune错误类型error指针(pointer)数组(array)切片(slice)字典(map)通道(chan)结构体(struct)接口(interface)复合类型Go语言语法16流程控制条件语句ifa5{return0}else{return1}选择语句switchi{case0:fmt.Printf(“0”)case1:fallthroughcase2,3:fmt.Printf(“2,3”)default:fmt.Printf(“default”)}Go语言语法17流程控制选择语句switch{case0=Num&&Num=3:fmt.Printf(“0-3”)case4=Num&&Num=6:fmt.Printf(“4-6”)}循环语句//case1sum:=0fori:=0;i10;i++{//条件表达式中也支持多重赋值sum+=i}//case2sum:=0for{//相当于while,do-whilesum++//支持按标签break}Go语言语法18流程控制跳转语句支持continue、break、goto,break可按标签选择中断到哪一个循环Go语言语法19函数函数定义funcAdd(aint,bint)(retint,errerror){ifa0||b0{err=errors.New(“error”)return}returna+b,nil//多重返回值}匿名函数和闭包函数的基本组成为:关键字func、函数名、参数列表、返回值、函数体和返回语句。匿名函数由一个不带函数名的函数声明和函数体组成。匿名函数可以直接赋值给一个变量或直接执行。闭包是可以包含自由变量的代码块。相当于Java中的嵌套匿名类Go语言语法20错误处理大多数函数将error作为最后一个返回值deferfuncCopyFile(dst,srcstring)(wint64,errerror){srcFile,err:=os.Open(src)iferr!=nil{return}defersrcFile.Close()}//清理多语句,使用匿名函数deferfunc(){//清理工作}()defer语句的含义是不管程序是否出现异常,均在函数退出时自动执行相关代码。四、面向对象编程面向对象编程22类型系统Go语言中的大多数类型都是值语义,并且都可以包含对应的操作方法。在需要的时候,你可以给任何类型(包括内置类型)增加新方法。而在实现某个接口时,无需从从该接口继承,只需要实现该接口要求的所有方法即可。typeIntegerintfunc(aInteger)Less(bInteger)bool{returnab}funcmain(){varaInteger=1ifa.Less(2){fmt.Println(a,“Less2”)}}面向对象编程23可见性Go语言中要使某个符号对其他包(package)可见,只需要将该符号定义为以大写字母开头,否则不可见。成员方法和成员变量的可见性遵循同样的规则。Go语言中符号的可访问性是包一级的而不是类型一级的。typeRectstruct{X,Yfloat64Width,Heightfloat64}func(r*Rect)area()float64{returnr.Width*r.Height}面向对象编程24接口非侵入式接口typeFilestruct{//…}func(f*File)Read(buf[]byte)(nint,errerror)func(f*File)Write(buf[]byte)(nint,errerror)func(f*File)Close()error在Go语言中,一个类只要实现了接口要求的所有函数,我们就说这个类实现了该接口。这种方式有如下几种好处:•Go语言不需要绘制类库的继承树图•实现类的时候,只需要关心自己应该提供哪些方法,不用纠结接口需要拆的多细才合适。•不用为了实现一个接口而导入一个包,减少耦合。面向对象编程25接口typeIFileinterface{Read(buf[]byte)(nint,errerror)Write(buf[]byte)(nint,errerror)Close()error}typeIReaderinterface{Read(buf[]byte)(nint,errerror)}typeIWriterinterface{Write(buf[]byte)(nint,errerror)}typeICloserinterface{Close()error}varfile1IFile=new(File)varfile2IReader=new(File)varfile3IWriter=new(File)varfile4ICloser=new(File)五、并发编程并发编程27协程Go语言在语言级别支持轻量级线程(即协程),叫goroutine。Go语言提供的所有系统调用操作都会出让CPU给其他goroutine。这让事情变得非常简单,让轻量级线程的切换管理不依赖于系统的线程和进程,也不依赖于CPU的核心数量。Go语言中最重要的一个特性是go关键字funcAdd(x,yint){z:=x+y}goAdd(2,1)//并发执行并发编程28并发通信工程上两种最常见的并发通信模型:共享数据消息一个大的系统中具有无数的锁、无数的共享变量、无数的业务逻辑与错误处理分支。采用共享数据将是一场噩梦。Go语言已并发编程作为最核心优势,提供了以消息机制而非共享内存作为通信方式的通信模型(channel)。channel是类型相关的的,一个channel只能传递一种类型的值,这个类型需要在声明的channel时指定。channel相当于一种类型安全的管道。并发编程29并发通信channelselect{case-chan1:casechan2-1:default:}一般channel的声明形式:varchanNamechanElementType定义一个channel:ch:=make(chanint)将一个数据写入channel:ch-value从channel中读取数据:value:=-chselectGo语言直接在语言级别支持select关键字,用于处理异步IO问题。select有比较多的限制,其中最大的限制就是每个case语句里必须是一个IO操作。并发编程30并发通信缓冲机制timeout:=make(chanbool,1)gofunc(){time.Sleep(1e9)//等待1秒timeout-true}()select{case-ch:case-timeout:default:}创建一个带缓冲的channel:c:=make(chanint,1024)超时机制Go语言没有提供直接的超时处理机制,但我们可以利用select机制实现一套并发编程31并发通信channel的传递typePipeDatastruct{valueinthandlerfunc(int)intnextchanint}funchandler(queuechan*PipeData){fordata:=rangequeue{data.next-data.handler(data.value)}}Go语言中channel本身是一个原生类型,因此channel可以传递。下面我们利用这个特性来实现*nix常见的管道特性并发编程32并发通信单向channelvarch1chanint//ch1是一个正常的channel,不是单向的varch2chan-float64//ch2是单向的,只用于写float64数据varch3-chanint//ch3是单向的,只用于读取int数据//单向channel与双向channel之间的转换ch4:=make(chanint)ch5:=-chanint(ch4)//ch5为单向的读取channelch6:=chan-int(ch4)//ch6为单向的写入channel我们在将一个channel变量传递到一个函数时,可以通过将其制定为