结构
结构的创建
root := TreeNode{value:3}
root.left = &TreeNode{}
root.right = &TreeNode{5,nil,nil}
root.right.left = new(TreeNode)
func createTreeNode(value int) *TreeNode {
return &TreeNode{value: value}
}
root.left.right = createTreeNode(6)
// 为结构定义方法
func (node TreeNode) print() {
fmt.Println(node.value)
}
// 使用指针作为方法接受者
func (node *TreeNode) setValue(value int) {
node.value = value
}
- 只有使用指针才可以改变结构内容
- nil指针也可以调用方法
值接受者 VS 指针接受者
- 要改变内容必须使用指针接受者
- 结构体过大也考虑使用指针接受者
- 一致性:如有指针接受者,最好都是指针接受者
- 值接受者是go特有的
封装
- 名字一般使用CamelCase
- 首字母大写:public
- 首字母小写:private
包
- 每一个目录一个包
- main包包含可执行入口
- 为结构定义的方法必须放在同一个包内
- 可以是不同的包
可以扩充系统类型或者别人的类型
- 定义别名
- 使用组合
接口
duck typing
duck typing
- 描述事物的外部行为而非内部结构
- “像鸭子走路,像鸭子叫(长得像鸭子),那么就是鸭子”
- 严格来说go属于结构化类型系统,类似duck typing
go语言的duck typing
- 同时具有python,C++的duck typing的灵活性
- 又具有java的类型检查
接口的定义
type Retriever interface {
Get(url string) string
}
func download(r Retriever) string {
return r.Get("http://www.imooc.com")
}
接口变量里面有什么
- 接口变量自带指针
- 接口变量同样采用值传递,几户不需要使用接口的指针
- 指针接受者实现只能以指针方式使用,值接受者都可
接口的组合
type RetrieverPoster interface {
Retriever
Poster
}
函数式编程
- 函数是一等公民:参数,变量,返回值都可以是函数
- 高阶函数
- 函数 -> 闭包
正统函数编程
- 不可变性:不能有状态,只有常量和函数
- 函数只有一个函数
资源管理和出错管理
defer调用
func tryDefer() {
for i :=0; i < 100; i++ {
defer fmt.Println(i)
if i == 30 {
panic("printed too many")
}
}
}
- 确保调用在函数结束时发生
- 参数在defer语句时计算
- defer列表为后进先出
何时使用defer调用
- Open/Close
- Lock/UnLock
- PrinterHeader/PrinterFooter
错误处理
func tryError(filename string) {
file, err := os.OpenFile(filename, os.O_EXCL|os.O_CREATE,0666)
if err != nil {
if pathError, ok := err.(*os.PathError); !ok {
panic(err)
} else {
fmt.Printf("%s,%s,%s\n",
pathError.Op,
pathError.Path,
pathError.Err)
}
return
}
defer file.Close()
}
网友评论