Go 语言里没有 class
- Go 和其它经典语言不同,它没有 class,没有对象,也没有继承。
- 但是 Go 提供了 struct 和方法。
将方法关联到 struct
- 方法可以被关联到你声明的类型上
package mainimport "fmt"// coordinate in degrees, minutes, seconds in a N/S/E/W hemisphere.type coordinate struct {d, m, s float64h rune}// decimal converts a d/m/s coordinate to decimal degrees.func (c coordinate) decimal() float64 {sign := 1.0switch c.h {case 'S', 'W', 's', 'w':sign = -1}return sign * (c.d + c.m/60 + c.s/3600)}func main() {// Bradbury Landing: 4º35'22.2" S, 137º26'30.1" Elat := coordinate{4, 35, 22.2, 'S'}long := coordinate{137, 26, 30.12, 'E'}fmt.Println(lat.decimal(), long.decimal())}
构造函数
- 可以使用 struct 复合字面值来初始化你所要的数据。
- 但如果 struct 初始化的时候还要做很多事情,那就可以考虑写一个构造用的函数。
- Go 语言没有专用的构造函数,但以 new 或者 New 开头的函数,通常是用来构造数据的。例如 newPerson(),NewPerson()
package mainimport "fmt"// location with a latitude, longitude.type location struct {lat, long float64}// coordinate in degrees, minutes, seconds in a N/S/E/W hemisphere.type coordinate struct {d, m, s float64h rune}// newLocation from latitude, longitude d/m/s coordinates.func newLocation(lat, long coordinate) location {return location{lat.decimal(), long.decimal()}}// decimal converts a d/m/s coordinate to decimal degrees.func (c coordinate) decimal() float64 {sign := 1.0switch c.h {case 'S', 'W', 's', 'w':sign = -1}return sign * (c.d + c.m/60 + c.s/3600)}func main() {curiosity := newLocation(coordinate{4, 35, 22.2, 'S'}, coordinate{137, 26, 30.12, 'E'})fmt.Println(curiosity)}
New 函数
- 有一些用于构造的函数的名称就是 New(例如 errors 包里面的 New 函数)。
- 这是因为函数调用时使用 包名.函数名 的形式。
- 如果该函数叫 NewError,那么调用的时候就是 errors.NewError(),这就不如 errors.New() 简洁
class 的替代方案
- Go 语言没有 class,但使用 struct 并配备几个方法也可以达到同样的效果。
package mainimport ("fmt""math")// location with a latitude, longitude.type location struct {lat, long float64}// world with a volumetric mean radius in kilometerstype world struct {radius float64}var mars = world{radius: 3389.5}// distance calculation using the Spherical Law of Cosines.func (w world) distance(p1, p2 location) float64 {s1, c1 := math.Sincos(rad(p1.lat))s2, c2 := math.Sincos(rad(p2.lat))clong := math.Cos(rad(p1.long - p2.long))return w.radius * math.Acos(s1*s2+c1*c2*clong)}// rad converts degrees to radians.func rad(deg float64) float64 {return deg * math.Pi / 180}func main() {spirit := location{-14.5684, 175.472636}opportunity := location{-1.9462, 354.4734}dist := mars.distance(spirit, opportunity)fmt.Printf("%.2f km\n", dist)}
作业题
- 使用例子(22.1、22.2、22.3)中的代码,编写一个程序。并为下表中每个位置都声明一个 location,以十进制度数打印出每个位置。
package mainimport "fmt"// location with a latitude, longitude.type location struct {lat, long float64}// coordinate in degrees, minutes, seconds in a N/S/E/W hemisphere.type coordinate struct {d, m, s float64h rune}// newLocation from latitude, longitude d/m/s coordinates.func newLocation(lat, long coordinate) location {return location{lat.decimal(), long.decimal()}}// decimal converts a d/m/s coordinate to decimal degrees.func (c coordinate) decimal() float64 {sign := 1.0switch c.h {case 'S', 'W', 's', 'w':sign = -1}return sign * (c.d + c.m/60 + c.s/3600)}func main() {spirit := newLocation(coordinate{14, 34, 6.2, 'S'}, coordinate{175, 28, 21.5, 'E'})opportunity := newLocation(coordinate{1, 56, 46.3, 'S'}, coordinate{354, 28, 24.2, 'E'})curiosity := newLocation(coordinate{4, 35, 22.2, 'S'}, coordinate{137, 26, 30.12, 'E'})insight := newLocation(coordinate{4, 30, 0.0, 'N'}, coordinate{135, 54, 0, 'E'})fmt.Println("Spirit", spirit)fmt.Println("Opportunity", opportunity)fmt.Println("Curiosity", curiosity)fmt.Println("InSight", insight)}
- 使用例子 22.4 中的 distance 方法,编写一个程序,来判定上题表中每对着陆点之间的距离。并回答:
- 哪两个着陆点之间最近?
- 哪两个着陆点之间最远?
- 计算伦敦到巴黎之间的距离(51°30’N 0°08’W) ,(48°51’N 2°21’E),地球半径为 6371 公里。
- 计算你的城市到北京距离
- 计算火星上 Mount Sharp (5°4’ 48”S, 137°51’E) 到 Olympus Mons (18°39’N, 226°12’E) 之间的距离。火星的半径是 3389.5 公里。
package mainimport ("fmt""math")// location with a latitude, longitude.type location struct {lat, long float64}// coordinate in degrees, minutes, seconds in a N/S/E/W hemisphere.type coordinate struct {d, m, s float64h rune}// newLocation from latitude, longitude d/m/s coordinates.func newLocation(lat, long coordinate) location {return location{lat.decimal(), long.decimal()}}// decimal converts a d/m/s coordinate to decimal degrees.func (c coordinate) decimal() float64 {sign := 1.0switch c.h {case 'S', 'W', 's', 'w':sign = -1}return sign * (c.d + c.m/60 + c.s/3600)}// world with a volumetric mean radius in kilometerstype world struct {radius float64}// distance calculation using the Spherical Law of Cosines.func (w world) distance(p1, p2 location) float64 {s1, c1 := math.Sincos(rad(p1.lat))s2, c2 := math.Sincos(rad(p2.lat))clong := math.Cos(rad(p1.long - p2.long))return w.radius * math.Acos(s1*s2+c1*c2*clong)}// rad converts degrees to radians.func rad(deg float64) float64 {return deg * math.Pi / 180}var (mars = world{radius: 3389.5}earth = world{radius: 6371})func main() {spirit := newLocation(coordinate{14, 34, 6.2, 'S'}, coordinate{175, 28, 21.5, 'E'})opportunity := newLocation(coordinate{1, 56, 46.3, 'S'}, coordinate{354, 28, 24.2, 'E'})curiosity := newLocation(coordinate{4, 35, 22.2, 'S'}, coordinate{137, 26, 30.12, 'E'})insight := newLocation(coordinate{4, 30, 0.0, 'N'}, coordinate{135, 54, 0, 'E'})fmt.Printf("Spirit to Opportunity %.2f km\n", mars.distance(spirit, opportunity))fmt.Printf("Spirit to Curiosity %.2f km\n", mars.distance(spirit, curiosity))fmt.Printf("Spirit to InSight %.2f km\n", mars.distance(spirit, insight))fmt.Printf("Opportunity to Curiosity %.2f km\n", mars.distance(opportunity, curiosity))fmt.Printf("Opportunity to InSight %.2f km\n", mars.distance(opportunity, insight))fmt.Printf("Curiosity to InSight %.2f km\n", mars.distance(curiosity, insight))london := newLocation(coordinate{51, 30, 0, 'N'}, coordinate{0, 8, 0, 'W'})paris := newLocation(coordinate{48, 51, 0, 'N'}, coordinate{2, 21, 0, 'E'})fmt.Printf("London to Paris %.2f km\n", earth.distance(london, paris))edmonton := newLocation(coordinate{53, 32, 0, 'N'}, coordinate{113, 30, 0, 'W'})ottawa := newLocation(coordinate{45, 25, 0, 'N'}, coordinate{75, 41, 0, 'W'})fmt.Printf("Hometown to Capital %.2f km\n", earth.distance(edmonton, ottawa))mountSharp := newLocation(coordinate{5, 4, 48, 'S'}, coordinate{137, 51, 0, 'E'})olympusMons := newLocation(coordinate{18, 39, 0, 'N'}, coordinate{226, 12, 0, 'E'})fmt.Printf("Mount Sharp to Olympus Mons %.2f km\n", mars.distance(mountSharp, olympusMons))}
