一、语法基础
- main函数在main包,每个代码文件中的init函数都将在main函数执行前调用。
- 同一文件夹中代码使用同一包名,且一般包与文件夹名一致。
- 同一包中的变量和类型、标识符可直接使用,包名类型命名空间,包中每个文件对应一个独立的职责。
- 将包导入其他文件中,可通过包名间接访问首字母大写的标识符,所定义的对象也只能访问首字母开头的成员变量或函数。
- 所有变量被初始化的零值:数值(0),字符串(""),布尔(false),指针(nil),引用类型(返回nil作为其值,但引用的底层数据结构会初始化为对应的零值)。
- Go中的引用类型有:map, slice, channel, func。
- 广泛使用指针或引用类型来传递变量,但其指针不支持指针运算。
- 函数定义(属于包)和方法定义(属于结构体)的区别
- 垃圾回收器GC:
二、常用数据结构及使用方法
1. map: map[key]value
//key类型须支持==和!=运算符,不能为浮点数 var matchers = make(map[string]string) ages := make(map[string]int),ages := make(map[string]int){} //空map //slice语法创建 ages := map[string]int{ "alice": 31, "charlie": 34, } 访问元素:ages["alice"] = 33 if age, ok := ages["bob"]; !ok { /* ... */ } //map中的元素不是变量,不能寻址 //遍历(遍历顺序不定) // 迭代切片里的元素 for name, age := range ages { fmt.Printf("%s\t%d\n", name, age) }
2. 数组:固定长度,较少使用
var arrInt [8]int td := [...]int{0,4,5,2} //数组引用(将数组引用或指针传入函数) func toZero(p *[32]byte){ for i := range p{ p[i] = 0 } } func toZero1(p *[32]byte){ *p = [32]byte{} }
3. slice: 底层使用数组实现,但长度可扩展,传递切片即引用同一对象
var names []string for name := range ages { names = append(names, name) } s := arr[:] //初始化切片为数组arr的引用 //提前给slice分配一个合适的大小,避免内存分配和拷贝 names := make([]string, 0, len(ages)) //创建一个空的slice,容量为len //在函数间传递切片
4. struct: 结构体或类型
type books struct { title string author string subject string id int } book := &books { title: "Go Lang", author: "peter" } book := books{"Go", "Peter"}
5. channel:
cStop := make(chan bool, 1) // Create an unbuffered channel. baton := make(chan int)
6. interface: 接口,可用于实现多态特性,只要某个结构体实现了接口类中的所有方法即可作为该接口的子类
type public interface { Topic() string Message() *Message Ack() error } type publication struct { d amqp.Delivery m *Message t string } func (p *publication) Ack() error { return p.d.Ack(false) } func (p *publication) Topic() string { return p.t } func (p *publication) Message() *Message { return p.m } func (p publication) Message() *Message { return p.m }
type PubSub struct { host string } type mock struct{} //其中mock和PubSub都实现了Publish和Subscribe两个接口 pubs := []publisher{ pubsub.New("localhost"), &mock{}, } for _, p := range pubs { p.Publish("key", "value") p.Subscribe("key") }
8. func: 函数或方法
func add(x, y int) int { return x + y } func swap(x, y string) (string, string) { return y, x } func add(x, y int) (z int) { z = x + y return } func sum(numbers ...int) int { s := 0 for i := range numbers{ s += i } return s } //匿名函数,闭包 var v func(a int) int v = func(a int) int { return a * a } fmt.Println(v(6)) //两种写法 v1 := func(i int) int { return i * i } fmt.Println(v1(7))
9. 继承与组合
/* 继承 一个结构体嵌到另一个结构体,称作组合 匿名和组合的区别 如果一个struct嵌套了另一个匿名结构体,那么这个结构可以直接访问匿名结构体的方法,从而实现继承 如果一个struct嵌套了另一个【有名】的结构体,那么这个模式叫做组合 如果一个struct嵌套了多个匿名结构体,那么这个结构可以直接访问多个匿名结构体的方法,从而实现多重继承 */ type Car struct { weight int name string } func (p *Car) Run() { fmt.Println("running") } type Bike struct { Car cycles int } package main import ( "fmt" ) type People struct{} type People2 struct{} func (p *People) ShowA() { fmt.Println("showA") p.ShowB() } func (p *People) ShowB() { fmt.Println("showB") } func (p *People) ShowC() { fmt.Println("showC") } func (p *People) ShowD() { fmt.Println("People:showD") } func (p *People2) ShowD() { fmt.Println("People2:showD") } type Teacher struct { People //组合People People2 //组合People2 } func (t *Teacher) ShowB() { fmt.Println("teacher showB") } func (t *Teacher) ShowC(arg string) { fmt.Println(arg) } func main() { t := Teacher{} //print showA //print showB t.ShowA() //print teacher showB t.ShowB() //print showB t.People.ShowB() //print test t.ShowC("test") //print showC t.People.ShowC() //因为组合方法中多次包含ShowD,所以调用时必须显示指定匿名方法 //print People2:showD t.People2.ShowD() }
10. 并发数据结构
//同步等待: var wg sync.WaitGroup wg.Add(2) defer wg.Done() wg.Wait() runtime.Gosched() //原子操作: atomic.AddInt64(&counter, 1) time.Sleep(1 * time.Second) atomic.StoreInt64(&shutdown, 1) atomic.LoadInt64(&shutdown) //加锁: mutex.Lock() mutex.Unlock() //随机数: rand.Seed(time.Now().UnixNano()) n := rand.Intn(100)
三、常用编程模式或框架
1. 并发模式
/* 1.runner包,调度后台处理任务,监视程序执行时间 【for-select结构】 通过执行返回可判断是超时、系统中断还是正常完成任务 2.pool包,有缓冲的通道实现资源池,管理多个协程间共享及独立使用的资源。[一组静态资源,数据库连接或内存缓冲区] 取得资源,归还资源,归还资源时应加互斥锁 3.work包,无缓冲通过,保证数据能及时处理,实时交换数据。生产者与消费者模型 */
2. 编解码
3. 单元测试和压力测试