参考书:Go语言编程
一 前言
1 Go语言在语言级别支持协程,叫goroutine
2 在执行体间的消息传递,有两个流派,一是共享内存模型,一是消息传递模型。Go语言偏向第二种。虽然也支持第一种。在Go语言中内置乐消息队列的支持,叫通道(channel),多个goroutine间可以通过通道进行交互
3 Go语言是强制统一代码风格的语言,如
3.1)变量大写字母开头自动表示为public变量,包外可见,小写字母开头为private变量,仅包内可见。所以Go语言没有public,private关键字
3.2){ } 也是强制要求如下风格
if expression {
}
3.3)Go语言的函数允许返回多个值
补充:大多数函数的最后一个返回值会为error类型。error类型只是一个系统内置的interface,如下
type error interface {
Error() string
}
4 Go语言反对函数和操作符重载,Go语言支持类,类成员方法,类的组合,但反对继承,反对虚函数和虚函数重载。但Go语言采用组合的文法来支持继承。
type Foo struct {
Base
...
}
func (foo *Foo) Bar(){
...
}
5 Go语言没有构造函数和析构函数。
6 在Go语言中,实现类的时候无需从接口派生,例子代码如下
type Foo struct {
...
}
var foo IFoo = new(Foo)
只要Foo实现了接口IFoo要求的所有方法,就实现了该接口,可以进行赋值。只要两个接口拥有相同的方法列表,那么他们就是等同的,可以互相赋值
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
第1章 初识Go语言
1 Go语言最主要的特性:
- 自动垃圾回收
- 更丰富的内置类型
- 函数多返回值
- 错误处理
- 匿名函数和闭包
- 类型和接口
- 并发编程
- 反射
- 语言交互性
2 Go语言内置map和支持数组切片slice
3 Go语言引入了3个关键字用于标准的错误处理流程,分别是defer,panic和recover
3.1 补充:在Go语言中,所有的函数也是值类型,可以作为参数传递。Go语言支持常规的匿名函数和闭包,如下所示
f := func(x,y int) int{
return x+y
}
3.2 补充:Go的interface例子
type Bird struct {
...
}
func (b *Bird) Fly(){
...
}
type IFly interface {
Fly()
}
func main(){
var fly IFly = new(Bird) // 因为Bird实现了IFly的方法
fly.Fly()
}
3.3 补充:Go语言通过系统的线程多路派遣这些函数的执行,使得每个用go关键字执行的函数可以运行成为一个单位协程。当某个协程阻塞时,调度器就会自动把其他协程安排到另外的线程中去执行,从而实现程序无等待并行化运行。
3.4 补充:Go语言实现了CSP(通信顺序进程,Communicating Sequential Process)模型作为goroutine间的推荐通信方式。在CSP模型中,一个并发系统由若干并行运行的顺序组成,每个进程不能对其他进程的变量赋值。进程间只能通过一对通信原语实现协作。Go语言用channel实现CSP。进程内创建的所有goroutinue运行在同一个内存地址空间中,因此如果不同的goroutine不得不去访问共享的内存变量,访问前应该先获取相应的读写锁。Go的sync包提供了读写锁功能。
package main
import "fmt"
func sum(values []int,resultChan chan int){
sum := 0
for _,value := range values {
sum += value
}
resultChan <- sum
}
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.Println("Result: ",sum1,sum2,sum1+sum2)
}
3.5 补充:Go语言的反射没有Java语言那样内置类型工厂,也不推荐读取配创建类型。
import (
"fmt"
"reflect"
)
type Bird struct {
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
4 每个Go源代码文件的开头都是一个package声明,表示该Go代码所属的包。包是Go语言最基本的分发单位。
5 要生成Go可执行程序,必须建立一个名为main的包,并且在该包中包含一个叫main()的函数。main( )函数不能带参数,也不能定义返回值。命令行传入的参数在os.Args变量中保存。
6 Go语言支持两种注释方法。
- /* 块注释 */
- // 行注释
7 Go语言并不强制要求每个语句后面要加上分号表示语句结束
8 用 run 直接运行程序命令
$ go run hello.go #将编译,链接和运行3个步骤合并一步,直接运行
9 用 build 命令编译结果但不自动运行
$ go build hello.go # 编译,生成一个hello文件
$ ./hello # 运行hello文件
补充:
1 golang中没有前置自增自减++i、--i,只可以后置自增自减
2 golang的main( )和init( )是自动被调用,init( )不能被别的函数调用。
3
func add(args ...int) int {
sum := 0
for _,arg := range args {
sum += arg
}
return sum
}
func main(){
fmt.Println(add(1,2)) // ok
fmt.Println(add(1,3,7)) // ok
fmt.Println(add([]int{1,2})) // error
fmt.Println(add([]int{1,2,3}...)) // ok
}