Go 语言里没有 class
- Go 和其它经典语言不同,它没有 class,没有对象,也没有继承。
- 但是 Go 提供了 struct 和方法。
将方法关联到 struct
- 方法可以被关联到你声明的类型上
package main
import "fmt"
// coordinate in degrees, minutes, seconds in a N/S/E/W hemisphere.
type coordinate struct {
d, m, s float64
h rune
}
// decimal converts a d/m/s coordinate to decimal degrees.
func (c coordinate) decimal() float64 {
sign := 1.0
switch 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" E
lat := 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 main
import "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 float64
h 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.0
switch 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 main
import (
"fmt"
"math"
)
// location with a latitude, longitude.
type location struct {
lat, long float64
}
// world with a volumetric mean radius in kilometers
type 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 main
import "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 float64
h 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.0
switch 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 main
import (
"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 float64
h 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.0
switch 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 kilometers
type 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))
}