入门
语言特性
- 高性能
- 自动垃圾回收
- 并发编程
- 网络库
- 编译速度快、交叉编译
基础语法
Hello World
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello World\n")
return 0
}
package main
:表示该代码文件属于main
包的一部分
import ("fmt")
:导入格式化库fmt
func main()
:程序执行入口
fmt.Println("Hello World\n")
:在标准化输出打印Hello World\n
定义变量
定义变量的方式有两种
var v Type [= value]
v := value
其中定义全局变量必须使用var
声明。
分支
if condition {}
switch [condition]:
case value | condition:
// ...
default:
// ...
循环
go语言中没有while关键字,使用for condition {}
实现
for i := 0; i < n; i++ {}
for i < n {}
for k, v := range array {}
数据结构
数组(array)
数组为一段定长序列,其定义方式为:
var arr [num]Type
arr := [num]Type{...}
数组在作为参数传递时,采用值传递(传递时会拷贝整个数组)而非引用传递,函数内无法直接对原数组修改。
切片(slice)
切片的是一段变长序列,可以动态的调整序列长度,其定义方式为:
s := make([]Type, length)
切片是一种引用类型的数据结构,其结构体为
// src/reflect/value.go
type SliceHeader struct {
Data uintptr // 指向序列首个元素的指针
Len int // 切片长度
Cap int // 切片容量
}
切片在作为参数传递时,只会拷贝该结构体,而非结构体内指针指向的序列。对结构体参数的修改不会影响原结构体,但可以修改所指向的元素,当函数内切片发生扩容时,函数内外的两个切片指向的底层序列将会不同。
Data
指向一段底层的连续序列,在序列满时,go会将申请一片新的连续的内存空间,将旧序列内容拷贝到新序列。在切列容量小于256时,增长策略时新序列容量为旧序列的翻倍,容量超过256后,新切片容量计算公式为:
且新切片的Data
指针指向的位置与旧切片的不相同。
切片循环访问方式:
for i := 0; i < len(arr); i++ {/* arr[i] */}
for idx, val := range(arr) {/* 不使用idx则改其为 _ */}
哈希表(map)
存储键值对的无序数据结构,其定义方式为:
mp := make(map[kType]vType)
mp := map[kType]vType{k1: v1, k2: v2, /*...*/ }
访问与删除方式为:
val, ok := mp[key]
if !ok {/* ... */}
delete(mp, key)
指针(pointer)
使用方式与C的指针类似,不同点:
- 不能允许指针运算
- 不允许指针间类型转换
unsafe.Pointer
为通用指针(unsafe)
函数(function)
func name(args Type) returns {}
当函数的参数为指针类型时,会拷贝指针作为形参,以便修改指向对象,但使得逃逸分析将对象分配到堆空间上而非栈空间,而降低访问速度以及带来堆内对象垃圾回收的成本,因此对于只读小对象时,直接拷贝对象传参可能性能会更好。
错误(error)
type error interface {
Error() string
}
从error的接口可知,创建一个error的关键是报错的信息。创建方式如下:
errors.New("error")
捕获与处理方式:
_, err := f()
if err != nil { /* ... */ }
结构体(struct)
type Item struct {
Name Type // public
id Type // private
}
func (r Name) function() {} // 值接收,不能直接改变结构体内成员
func (r *Name) function() {} // 指针接收,能直接改变结构体内成员
面向对象
面向对象三要素:封装、继承、多态
封装
结构体内包装属性和方法,使用属性名和方法名的开头大小写控制可见性,大写为public,小写为private。
继承
不同于Java的关键字extends
,go使用匿名字段实现类似的功能。
type Card struct {
Item // 匿名字段
}
//访问方式
card.Name // 而非card.Item.Name
多态
go提供接口interface来提供多继承和多态功能,例如:
// in sort.Interface
type Interface interface {
// Len is the number of elements in the collection.
Len() int
// Less reports whether the element with
// index i should sort before the element with index j.
Less(i, j int) bool
// Swap swaps the elements with indexes i and j.
Swap(i, j int)
}
// implementation
type Cards []card
func (a Cards) Len() int { return len(a) }
func (a Cards) Less(i, j int) bool { return a[i].id < a[j].id }
func (a Cards) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
通过自定义Len
、Less
、Swap
方法,实现sort的接口,就可以使用sort.Sort
函数排序自定义类型,每个类型的基于自己的sort.Sort
实现不同排序规则,即为多态。