Go In Action

《Go语言实战》


1. 关于Go语言介绍

1.1 开发速度

Go语言简化了解决依赖的算法, 提供了更快的编译器, 编译Go程序时, 编译器只会关注那些直接被引用的库,而不是像Java, C那样, 要遍历所有依赖的库.

1.2 并发
  • Goroutine
    在Go语言中会使用同一个线程来执行多个goroutine. Go语言运行时会自动在配置的一组逻辑处理器(Logistic CPU)上调度执行goroutine, 每个逻辑处理器(Logistic CPU)绑定到一个操作系统线程上.
  • Chan
    通道是一种数据结构, 可以让goroutine之间进行安全的数据通信. 通道可以让帮用户避免其他语言里常见的共享内存访问的问题.
    需要强调的是, 通道并不提供跨goroutine的数据访问保护机制: 1.如果通过通道传输数据的一个副本, 那么每个goroutine都持有一份副本, 各自对自己的副本做修改是安全的; 2.当传输的是指向数据的指针, 如果读和写是由不同的goroutine完成的, 每个goroutine依旧需要额外的同步动作.
1.3 Go语言的类型系统
  • Go语言提供了无继承的类型系统
  • Go开发者使用组合(Composition)设计模式, 只需要简单地将一个类型嵌入到另一个类型, 就能复用所有的功能.
  • Go语言具有独特的接口实现机制, 允许用户对行为进行建模, 而不是对类型(type)进行建模. 在Go语言中, 不需要声明某个类型(type)实现了某个interface, 编译器会判断一个类型(type)的实例是否符合正在使用的interface.
  • Go语言中, 如果一个类型实现了一个interface的所有方法, 那么这个类型(type)的实例就可以存储在这个interface的实例中.
1.4 内存管理

Go语言拥有现代化的垃圾回收机制.


2. 快速开始一个Go程序

2.1 Go语言包导入语法
1
2
3
4
5
6
7
8
9
10
11
import "fmt"

import "./model" //相对路径导入

import "shorturl/model" //绝对路径导入, 加载$GOPATH/src/shorturl/model

import ."fmt" //点操作: 可以直接省略fmt.Println()为Println()

import f"fmt" //别名: fmt.Println()->f.Println()

import _"fmt" //仅仅执行init(), 无法通过包名来调用包中导出的函数;导入fmt包, 但是不使用它
2.2 main包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main //如果main函数不在main包里, 构建工具不会生成可执行文件

import(
"log"
"os" //Go语言里, 不允许导入某个包, 但是不使用它("_"导入除外)
)

//init()函数在main之前调用
func init(){
//将日志输出到标准输出
log.SetOutput(os.Stdout)
}
var Count int //在Go语言里, 标识符(变量、方法、类型、接口)要么从包里公开, 要么不从包里公开

funt main(){

}
2.3 变量初始值

在Go语言里, 所有变量都被初始化其零值:

    1. 数值类型: 0
    1. string : “”
    1. boolean : false
    1. 指针 : nil
    1. 引用类型 : 所引用的底层数据结构会被初始化为对应的零值.

3. 打包和工具链


4. 数组、切片和映射


5. Go语言的类型系统


6. 并发


7. 并发模式


8. 标准库


9. 测试和性能


10. 反射

Go Reflect 理解)
Go语言的反射机制在很多标准库和三方库源码中被使用到, 特别是配合空接口interface{}, 让原本是静态类型的go具备了很多动态类型语言的特征.
reflect有两个重要的类型reflect.Type和reflect.Value, 分别对应于对象的类型和值.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package main

import (
"fmt"
"reflect"
)

type Foo struct {
x string
y int
}

func (foo Foo)Do() {
fmt.Printf("{x=%s, y=%d}\n",foo.x,foo.y)
}

func main() {

var i int = 123
var f float32 = 1.23
var strs []string = []string{"Hello", "World", "Welcome"}

//reflect.Type & reflect.Value
fmt.Println("*****************Type&Value****************************")
fmt.Printf("i's type is %s, i's value is %d\n",reflect.TypeOf(i),reflect.ValueOf(i))
fmt.Printf("f's type is %s, f's value is %f\n",reflect.TypeOf(f),reflect.ValueOf(f))
fmt.Printf("strs's type is %s, strs's value is %s\n",reflect.TypeOf(strs),reflect.ValueOf(strs))
fmt.Println("*****************Type&Value****************************\n\n")

var foo Foo = Foo{"CHina",123}
typ := reflect.TypeOf(foo)
fmt.Println(typ)
fmt.Println(typ.Name())
fmt.Println(typ.String())

//type.Field
fmt.Println("*****************Field****************************")
for n := 0; n < typ.NumField(); n++ {
field := typ.Field(n)
fmt.Printf("Field %s's type is %s\n", field.Name, field.Type)
}

field_y, _ := typ.FieldByName("y")
fmt.Printf("Field %s's type is %s, and TAG is %s\n", field_y.Name, field_y.Type,field_y.Tag)
fmt.Println("*****************Field****************************\n\n")


/**type.Kind**/
fmt.Println("*****************Kind****************************")
fmt.Printf("x.Kind() is %s\n",reflect.TypeOf(i).Kind())
fmt.Printf("f.Kind() is %s\n",reflect.TypeOf(f).Kind())
fmt.Printf("strs.Kind() is %s\n",reflect.TypeOf(strs).Kind())
fmt.Printf("typ.Kind() is %s\n",typ.Kind())
fmt.Println("*****************Kind****************************\n\n")

//
fmt.Println("*****************interface****************************")
fmt.Println(reflect.ValueOf(i).Interface())
fmt.Println(reflect.ValueOf(f).Interface())
fmt.Println(reflect.ValueOf(strs).Interface())
fmt.Println(reflect.ValueOf(foo).Interface())
fmt.Println("*****************interface****************************\n\n")


fmt.Println("*****************value.Field****************************")
val:= reflect.ValueOf(foo)
fmt.Println(val.FieldByName("x"))
fmt.Println(val.FieldByName("y"))
fmt.Println("*****************value.Field****************************\n\n")


fmt.Println("*****************利用reflct对value赋值****************************")
fmt.Printf("f不能赋值%t\n",reflect.ValueOf(f).CanSet())
fmt.Printf("foo不能赋值%t\n",reflect.ValueOf(foo).CanSet())
fmt.Printf("可以赋值%t\n",reflect.ValueOf(&f).Elem().CanSet())
fmt.Printf("可以赋值%t\n",reflect.ValueOf(&foo).Elem().CanSet())
fmt.Printf("修改之前的float: f=%f\t",f)
fe := reflect.ValueOf(&f).Elem()
fe.SetFloat(0.25)
fmt.Printf("修改之后的float: f=%f\n",f)
fmt.Println("*****************利用reflect对value赋值****************************\n\n")

//Method
fmt.Println("*****************利用reflect进行方法调用: 方法名称必须大写****************************")
value := reflect.ValueOf(foo)
for j:=0;j<value.NumMethod();j++{
methd := value.Method(j)
fmt.Printf("Method-1: name=%s\n",methd)
methd.Call([]reflect.Value{})
}
reflect.ValueOf(&foo).MethodByName("Do").Call([]reflect.Value{})
fmt.Println("*****************利用reflect进行方法调用: 方法名称必须大写****************************\n\n")
}