Go 学习笔记 5(1) - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
xiangdong1987
V2EX    Go 编程语言

Go 学习笔记 5(1)

  •  
  •   xiangdong1987 2019-05-16 17:57:30 +08:00 2707 次点击
    这是一个创建于 2428 天前的主题,其中的信息可能已经有所发展或是发生改变。

    从 90 年代早期开始,面向对象编程(OOP)就成为了称霸工程界和教育界的编程范式,所以之后几乎所有大规模被应用的语言都包含了对 OOP 的支持,go 语言也不例外。OOP 编程的第一方面,我们会向你展示如何有效地定义和使用方法。我们会覆盖到 OOP 编程的两个关键点,封装和组合。

    方法声明

    • 在函数声明时,在其名字之前放上一个变量,即是一个方法。这个附加的参数会将该函数附加到这种类型上,即相当于为这种类型定义了一个独占的方法。
    package geometry import "math" type Point struct{ X, Y float64 } // traditional functionfunc Distance(p, q Point) float64 { return math.Hypot(q.X-p.X, q.Y-p.Y) } // same thing, but as a method of the Point typefunc (p Point) Distance(q Point) float64 { return math.Hypot(q.X-p.X, q.Y-p.Y) } 
    • 上面的代码里那个附加的参数 p,叫做方法的接收器(receiver),早期的面向对象语言留下的遗产将调用一个方法称为“向一个对象发送消息”。
    • 在 go 语言中不适用 this self 做方法接收器,它建议适用类型的首字母作为接收器简短一致。
    • 包级的方法不会跟类型的方法产生混乱
    // A Path is a journey connecting the points with straight lines.type Path []Point // Distance returns the distance traveled along the path.func (path Path) Distance() float64 { sum := 0.0 for i := range path { if i > 0 { sum += path[i-1].Distance(path[i]) } } return sum } perim := Path{ {1, 1}, {5, 1}, {5, 4}, {1, 1}, } fmt.Println(perim.Distance()) // "12" 
    • 在上面两个对 Distance 名字的方法的调用中,编译器会根据方法的名字以及接收器来决定具体调用的是哪一个函数。第一个例子中 path[i-1]数组中的类型是 Point,因此 Point.Distance 这个方法被调用;在第二个例子中 perim 的类型是 Path,因此 Distance 调用的是 Path.Distance。
    • 对于一个给定的类型,其内部的方法都必须有唯一的方法名,但是不同的类型却可以有同样的方法名,比如我们这里 Point 和 Path 就都有 Distance 这个名字的方法;所以我们没有必要非在方法名之前加类型名来消除歧义,比如 PathDistance。
    import "gopl.io/ch6/geometry" perim := geometry.Path{{1, 1}, {5, 1}, {5, 4}, {1, 1}} fmt.Println(geometry.PathDistance(perim)) // "12", standalone function fmt.Println(perim.Distance()) // "12", method of geometry.Path 
    • 如果我们要用方法去计算 perim 的 distance,还需要去写全 geometry 的包名,和其函数名,但是因为 Path 这个变量定义了一个可以直接用的 Distance 方法,所以我们可以直接写 perim.Distance()。相当于可以少打很多字,作者应该是这个意思。因为在 Go 里包外调用函数需要带上包名,还是挺麻烦的。

    基于指针的对象方法

    • 不管你的 method 的 receiver 是指针类型还是非指针类型,都是可以通过指针 /非指针类型进行调用的,编译器会帮你做类型转换。在声明一个 method 的 receiver 该是指针还是非指针类型时,你需要考虑两方面的内部,
      • 第一方面是这个对象本身是不是特别大,如果声明为非指针变量时,调用会产生一次拷贝;
      • 第二方面是如果你用指针类型作为 receiver,那么你一定要注意,这种指针类型指向的始终是一块内存地址,就算你对其进行了拷贝。熟悉 C 或者 C 艹的人这里应该很快能明白。
    目前尚无回复
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1108 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 22ms UTC 18:08 PVG 02:08 LAX 10:08 JFK 13:08
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86