函数
声明
func name(parameter-list) (result-list){
body
}
递归
多返回值
语法
// 用逗号隔开
return a, b
base return
如果返回值变量名在函数体内出现,return可以省略操作数。
错误
Go使用if和return处理异常,出现异常就返回
函数值
函数拥有类型,可以被赋值给其他变量,函数类型的0值是nil,不能调用值为nil的函数
匿名函数
5.6
可变参数
5.7
deferred函数
defer后面的函数会被延迟执行。直到包含该defer语句的函数执行完毕,defer后面的函数才会被执行。可以用于处理成对的操作,比如打开、关闭,加锁、释放锁
panic异常
Recover捕获异常
方法
方法和函数的最大区别是方法有接收者(从属),即方法都是有主人的。
声明
package geometry
import "math"
type Point struct{ X, Y float64 }
// traditional function
func Distance(p, q Point) float64 {
return math.Hypot(q.X-p.X, q.Y-p.Y)
}
// 方法,p Point代表方法的接收器
func (p Point) Distance(q Point) float64 {
return math.Hypot(q.X-p.X, q.Y-p.Y)
}
p := Point{1, 2}
q := Point{4, 6}
// 下面两种一个是函数,一个是方法
fmt.Println(Distance(p, q)) // "5", function call
fmt.Println(p.Distance(q)) // "5", method call
基于指针对象的方法
声明
func (p *Point) ScaleBy(factor float64) {
p.X *= factor
p.Y *= factor
}
调用
不管接收器是指针类型还是非指针类型,都可以通过指针/非指针类型进行调用,编译器会自动类型转换
r := &Point{1, 2}
r.ScaleBy(2)
p := Point{1, 2}
p.ScaleBy(2) // 会自动隐式调用&p来调用这个方法
通过嵌入结构体来扩展类型
// ColoredPoint 不是一个point,但是has a point,ColoredPoint拥有从Point引入的Distance等方法
type Point struct{ X, Y float64 }
type ColoredPoint struct {
Point
Color color.RGBA
}
可以直接通过ColoredPoint 去访问Point内的X和Y,比如cp.X
var cp ColoredPoint
cp.X = 1
fmt.Println(cp.Point.X) // "1"
cp.Point.Y = 2
fmt.Println(cp.Y) // "2"
可以把ColoredPoint类型当作接收器调用Point的方法
red := color.RGBA{255, 0, 0, 255}
blue := color.RGBA{0, 0, 255, 255}
var p = ColoredPoint{Point{1, 1}, red}
var q = ColoredPoint{Point{5, 4}, blue}
fmt.Println(p.Distance(q.Point)) // "5"
p.ScaleBy(2)
q.ScaleBy(2)
fmt.Println(p.Distance(q.Point)) // "10"
方法值和方法表达式
p := Point{1, 2}
q := Point{4, 6}
distanceFromP := p.Distance // method value
fmt.Println(distanceFromP(q)) // "5"
接口
接口是golang中实现多态性的唯一好途径。
看到一个接口类型的值时,不知道它是什么,唯一知道的是可以通过它的方法来做什么
概念:https://blog.csdn.net/u011957758/article/details/81150622
深挖:https://www.jianshu.com/p/82436645927b
定义接口
// 输出value is <nil> type is <nil>
// 接口本身的值和类型是nil
package main
import "fmt"
type Shape interface {
Area() float64
}
func main() {
var s Shape
fmt.Println("value is", s)
fmt.Printf("type is %T\n", s)
}
实现接口
我们创建了Shape接口和矩形结构体类型Rect。 然后我们使用Rect接收器类型定义了Area方法。 因此Rect实现了这些方法。 由于这些方法是由Shape接口定义的,因此Rect实现了Shape接口。
/*
输出
value is {5 4}
type is main.Rect
area is 20
s == r is true
*/
package main
import "fmt"
type Shape interface {
Area() float64
}
type Rect struct {
width float64
height float64
}
func (r Rect) Area() float64 {
return r.width * r.height
}
func main() {
var s Shape
s = Rect{5.0, 4.0}
r := Rect{5.0, 4.0}
fmt.Println("value is", s)
fmt.Printf("type is %T\n", s)
fmt.Println("area is ", s.Area())
fmt.Println("s == r is ", s == r)
}