Go 语言里没有 class

  • Go 和其它经典语言不同,它没有 class,没有对象,也没有继承。
  • 但是 Go 提供了 struct 和方法。

将方法关联到 struct

  • 方法可以被关联到你声明的类型上
  1. package main
  2. import "fmt"
  3. // coordinate in degrees, minutes, seconds in a N/S/E/W hemisphere.
  4. type coordinate struct {
  5. d, m, s float64
  6. h rune
  7. }
  8. // decimal converts a d/m/s coordinate to decimal degrees.
  9. func (c coordinate) decimal() float64 {
  10. sign := 1.0
  11. switch c.h {
  12. case 'S', 'W', 's', 'w':
  13. sign = -1
  14. }
  15. return sign * (c.d + c.m/60 + c.s/3600)
  16. }
  17. func main() {
  18. // Bradbury Landing: 4º35'22.2" S, 137º26'30.1" E
  19. lat := coordinate{4, 35, 22.2, 'S'}
  20. long := coordinate{137, 26, 30.12, 'E'}
  21. fmt.Println(lat.decimal(), long.decimal())
  22. }

构造函数

  • 可以使用 struct 复合字面值来初始化你所要的数据。
  • 但如果 struct 初始化的时候还要做很多事情,那就可以考虑写一个构造用的函数。
  • Go 语言没有专用的构造函数,但以 new 或者 New 开头的函数,通常是用来构造数据的。例如 newPerson(),NewPerson()
  1. package main
  2. import "fmt"
  3. // location with a latitude, longitude.
  4. type location struct {
  5. lat, long float64
  6. }
  7. // coordinate in degrees, minutes, seconds in a N/S/E/W hemisphere.
  8. type coordinate struct {
  9. d, m, s float64
  10. h rune
  11. }
  12. // newLocation from latitude, longitude d/m/s coordinates.
  13. func newLocation(lat, long coordinate) location {
  14. return location{lat.decimal(), long.decimal()}
  15. }
  16. // decimal converts a d/m/s coordinate to decimal degrees.
  17. func (c coordinate) decimal() float64 {
  18. sign := 1.0
  19. switch c.h {
  20. case 'S', 'W', 's', 'w':
  21. sign = -1
  22. }
  23. return sign * (c.d + c.m/60 + c.s/3600)
  24. }
  25. func main() {
  26. curiosity := newLocation(coordinate{4, 35, 22.2, 'S'}, coordinate{137, 26, 30.12, 'E'})
  27. fmt.Println(curiosity)
  28. }

New 函数

  • 有一些用于构造的函数的名称就是 New(例如 errors 包里面的 New 函数)。
  • 这是因为函数调用时使用 包名.函数名 的形式。
  • 如果该函数叫 NewError,那么调用的时候就是 errors.NewError(),这就不如 errors.New() 简洁

class 的替代方案

  • Go 语言没有 class,但使用 struct 并配备几个方法也可以达到同样的效果。
  1. package main
  2. import (
  3. "fmt"
  4. "math"
  5. )
  6. // location with a latitude, longitude.
  7. type location struct {
  8. lat, long float64
  9. }
  10. // world with a volumetric mean radius in kilometers
  11. type world struct {
  12. radius float64
  13. }
  14. var mars = world{radius: 3389.5}
  15. // distance calculation using the Spherical Law of Cosines.
  16. func (w world) distance(p1, p2 location) float64 {
  17. s1, c1 := math.Sincos(rad(p1.lat))
  18. s2, c2 := math.Sincos(rad(p2.lat))
  19. clong := math.Cos(rad(p1.long - p2.long))
  20. return w.radius * math.Acos(s1*s2+c1*c2*clong)
  21. }
  22. // rad converts degrees to radians.
  23. func rad(deg float64) float64 {
  24. return deg * math.Pi / 180
  25. }
  26. func main() {
  27. spirit := location{-14.5684, 175.472636}
  28. opportunity := location{-1.9462, 354.4734}
  29. dist := mars.distance(spirit, opportunity)
  30. fmt.Printf("%.2f km\n", dist)
  31. }

作业题

  • 使用例子(22.1、22.2、22.3)中的代码,编写一个程序。并为下表中每个位置都声明一个 location,以十进制度数打印出每个位置。

没有class - 图1

  1. package main
  2. import "fmt"
  3. // location with a latitude, longitude.
  4. type location struct {
  5. lat, long float64
  6. }
  7. // coordinate in degrees, minutes, seconds in a N/S/E/W hemisphere.
  8. type coordinate struct {
  9. d, m, s float64
  10. h rune
  11. }
  12. // newLocation from latitude, longitude d/m/s coordinates.
  13. func newLocation(lat, long coordinate) location {
  14. return location{lat.decimal(), long.decimal()}
  15. }
  16. // decimal converts a d/m/s coordinate to decimal degrees.
  17. func (c coordinate) decimal() float64 {
  18. sign := 1.0
  19. switch c.h {
  20. case 'S', 'W', 's', 'w':
  21. sign = -1
  22. }
  23. return sign * (c.d + c.m/60 + c.s/3600)
  24. }
  25. func main() {
  26. spirit := newLocation(coordinate{14, 34, 6.2, 'S'}, coordinate{175, 28, 21.5, 'E'})
  27. opportunity := newLocation(coordinate{1, 56, 46.3, 'S'}, coordinate{354, 28, 24.2, 'E'})
  28. curiosity := newLocation(coordinate{4, 35, 22.2, 'S'}, coordinate{137, 26, 30.12, 'E'})
  29. insight := newLocation(coordinate{4, 30, 0.0, 'N'}, coordinate{135, 54, 0, 'E'})
  30. fmt.Println("Spirit", spirit)
  31. fmt.Println("Opportunity", opportunity)
  32. fmt.Println("Curiosity", curiosity)
  33. fmt.Println("InSight", insight)
  34. }
  • 使用例子 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 公里。
  1. package main
  2. import (
  3. "fmt"
  4. "math"
  5. )
  6. // location with a latitude, longitude.
  7. type location struct {
  8. lat, long float64
  9. }
  10. // coordinate in degrees, minutes, seconds in a N/S/E/W hemisphere.
  11. type coordinate struct {
  12. d, m, s float64
  13. h rune
  14. }
  15. // newLocation from latitude, longitude d/m/s coordinates.
  16. func newLocation(lat, long coordinate) location {
  17. return location{lat.decimal(), long.decimal()}
  18. }
  19. // decimal converts a d/m/s coordinate to decimal degrees.
  20. func (c coordinate) decimal() float64 {
  21. sign := 1.0
  22. switch c.h {
  23. case 'S', 'W', 's', 'w':
  24. sign = -1
  25. }
  26. return sign * (c.d + c.m/60 + c.s/3600)
  27. }
  28. // world with a volumetric mean radius in kilometers
  29. type world struct {
  30. radius float64
  31. }
  32. // distance calculation using the Spherical Law of Cosines.
  33. func (w world) distance(p1, p2 location) float64 {
  34. s1, c1 := math.Sincos(rad(p1.lat))
  35. s2, c2 := math.Sincos(rad(p2.lat))
  36. clong := math.Cos(rad(p1.long - p2.long))
  37. return w.radius * math.Acos(s1*s2+c1*c2*clong)
  38. }
  39. // rad converts degrees to radians.
  40. func rad(deg float64) float64 {
  41. return deg * math.Pi / 180
  42. }
  43. var (
  44. mars = world{radius: 3389.5}
  45. earth = world{radius: 6371}
  46. )
  47. func main() {
  48. spirit := newLocation(coordinate{14, 34, 6.2, 'S'}, coordinate{175, 28, 21.5, 'E'})
  49. opportunity := newLocation(coordinate{1, 56, 46.3, 'S'}, coordinate{354, 28, 24.2, 'E'})
  50. curiosity := newLocation(coordinate{4, 35, 22.2, 'S'}, coordinate{137, 26, 30.12, 'E'})
  51. insight := newLocation(coordinate{4, 30, 0.0, 'N'}, coordinate{135, 54, 0, 'E'})
  52. fmt.Printf("Spirit to Opportunity %.2f km\n", mars.distance(spirit, opportunity))
  53. fmt.Printf("Spirit to Curiosity %.2f km\n", mars.distance(spirit, curiosity))
  54. fmt.Printf("Spirit to InSight %.2f km\n", mars.distance(spirit, insight))
  55. fmt.Printf("Opportunity to Curiosity %.2f km\n", mars.distance(opportunity, curiosity))
  56. fmt.Printf("Opportunity to InSight %.2f km\n", mars.distance(opportunity, insight))
  57. fmt.Printf("Curiosity to InSight %.2f km\n", mars.distance(curiosity, insight))
  58. london := newLocation(coordinate{51, 30, 0, 'N'}, coordinate{0, 8, 0, 'W'})
  59. paris := newLocation(coordinate{48, 51, 0, 'N'}, coordinate{2, 21, 0, 'E'})
  60. fmt.Printf("London to Paris %.2f km\n", earth.distance(london, paris))
  61. edmonton := newLocation(coordinate{53, 32, 0, 'N'}, coordinate{113, 30, 0, 'W'})
  62. ottawa := newLocation(coordinate{45, 25, 0, 'N'}, coordinate{75, 41, 0, 'W'})
  63. fmt.Printf("Hometown to Capital %.2f km\n", earth.distance(edmonton, ottawa))
  64. mountSharp := newLocation(coordinate{5, 4, 48, 'S'}, coordinate{137, 51, 0, 'E'})
  65. olympusMons := newLocation(coordinate{18, 39, 0, 'N'}, coordinate{226, 12, 0, 'E'})
  66. fmt.Printf("Mount Sharp to Olympus Mons %.2f km\n", mars.distance(mountSharp, olympusMons))
  67. }