这是我参与「第三届青训营 -后端场」笔记创作活动的第4篇笔记
面向对象
- Go语言仅支持封装,不支持继承和多态
- Go语言没有class,只有struct
- 不管指针还是实例,都是一路
.
下去,而不是->
结构的创建
func createNode(value int) *treeNode { //工厂函数
return &treeNode{value: value}
}
root.left.right = createNode(2)
- 使用自定义工厂函数
- 注意返回了局部变量的地址!
结构创建在堆上还是栈上?
不需要知道。有垃圾回收机制
显示定义和命名方法接收者
func (node TreeNode) print() {
fmt.Println(node.value)
}
使用指针作为方法接收者
func (node *TreeNode) setValue(value int) {
node.value = value
}
- 只有使用指针才可以改变结构内容,否则是值传递
nil
指针也可以调用方法
值接收者 VS. 指针接收者
- 要改变内容必须使用指针接收者
- 结构过大考虑使用指针接收者
- 一致性:如有指针接收者,最好都是指针接收者
- 值接收者是 Go语言特有
- 值/指针接收者均可接受 值/指针
封装
- 名字一般使用CamelCase
- 首字母大写:public
- 首字母小写:private
包
- 每个目录一个包
- main包比较特殊,有一个可执行的入口
- 为结构定义的方法必须放在同一个包内
- 可以是不同文件
如何扩充系统类型或者别人的类型
- 定义别名:最简单
- 使用组合:最常用
- 使用内嵌Embedding:需要省下许多代码(Go语言特殊性)
依赖管理
- 依赖管理
- 依赖管理的三个阶段GOPATH,GOVENDOR,go mod
注意:GOPATH下必须创建src
文件夹,若找不到包,从GOROOT和GOPATH去找
创建vendor
文件夹解决版本不同的问题,先从vendor
文件夹去找
vendor -> GOROOT -> GOPATH
第三方依赖管理工具:dep 、glide
glide.yaml
Go mod使用
go get -u
go build ./...
从import里直接go mod
go mod init name
含有main函数的文件必须放在自己单独的一个文件夹里。
接口
动态语言 & 静态语言 -> 类型
package main
import (
"chapter2/infra"
"fmt"
)
func getRetriever() retriever {
return infra.Retriever{}
}
//?: Something that Can "Get"
type retriever interface {
Get(string) string
}
func main() {
var r retriever = getRetriever()
fmt.Println(r.Get("https://www.imooc.com"))
}
duck typing
“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
- 描述事物的外部行为而非内部结构
- 严格说Go属于结构化类型系统,类似duck typing
//C++中的duck typing
template <class R>
string download(const R& retriever) {
return retriever.get("www.baidu.com")
}
接口的定义
使用者 ————> 实现者
downloader retriever
- 接口由使用者定义
- 接口的实现是隐式的,只要实现接口里的方法
接口变量里面有实现者的类型,也有指针和值
接口的值类型:类型和值
类型和值可以用swithc打印出来
也可以用Type assertion
package main
import (
"chapter2/retriever/mock"
"chapter2/retriever/real"
"fmt"
"time"
)
type Retriever interface {
Get(url string) string
}
func download(r Retriever) string {
return r.Get("https://www.imooc.com")
}
func main() {
var r Retriever
r = mock.Retriever{"this is a fake imooc.com"}
inspect(r)
r = &real.Retriever{
UserAgent: "Mozila/5.0",
TimeOut: time.Minute,
}
inspect(r)
//Type assertion
realRetriever := r.(*real.Retriever)
fmt.Println(realRetriever.TimeOut)
//fmt.Println(download(r))
}
func inspect(r Retriever) {
fmt.Printf("%T %v\n", r, r)
switch v := r.(type) {
case mock.Retriever:
fmt.Println("Contents: ", v.Contents)
case *real.Retriever:
fmt.Println("UserAgent: ", v.UserAgent)
}
}
查看接口变量
- 表示任何类型:interface{}
- Type Assertion
- Type Switch
接口的组合
type ReaderWriter interface {
Reader
Writer
}
常用系统接口
Stringer
Reader/Writer