• 作为函数参数,值类型就是值类型,指针类型就是指针类型

• 方法有一个值类型和指针类型的接受者时,都可以直接调用,内部会

自动进行语法的转换。

一个方法只是一个函数,它有一个特殊的接收者(receiver)类型,该接收者放在 func 关键字和函数名之间。接收者可以是结构体类型或非结构体类型。可以在方法内部访问接收者。

一般语法为:

func (t receiver_type) methodName(parameter list) {}

一、参数 receiver 类型可以是 T 或 *T。以指针为接收者也是可以的。两者的区别在于, 以*T为接收者时,方法内部对其的修改对于外部有效,而以 T作为接受者时,对于外部无效。

1func(e Employee)changeName(newName string){

2e.name = newName

3}

4func(e *Employee)changeAge(newAge int){

5e.age = newAge

6}

7emp1 := Employee{

8name: "张三",

9salary: 6000,

10currency: "$",

11age: 18,

12Address: Address{ "山东", "济南"},

13}

14emp1.displaySalary()

15

16fmt.Println( "Before call changeName ", emp1.name)

17//修改名字,未发生变化因为是值传递

18emp1.changeName( "zhangsan")

19fmt.Println( "After call changeName ", emp1.name) //After call changeName 张三

20

21fmt.Println( "Before change age", emp1.age)

22//利用指针来修改年龄

23emp1.changeAge( 50)

24fmt.Println( "After change age", emp1.age) //After change age 50

二、Go 不允许同名函数,但是同名方法可以定义在不同的类型上

1//Rectangle 代码规范

2typeRectangle struct{

3width float32

4height float32

5}

6//Circle 代码规范

7typeCircle struct{

8radius float32

9}

10func(e Employee)changeName(newName string){

11e.name = newName

12}

13func(e *Employee)changeAge(newAge int){

14e.age = newAge

15}

16funcmain(){

17//计算面积

18re := Rectangle{ 20, 30}

19c := Circle{ 40}

20//两个类型调用同名方法

21fmt.Println(re.getArea())

22fmt.Println(c.getArea())

23}

三、提阶,方法也支持提阶

1emp1 := Employee{

2name: "张三",

3salary: 6000,

4currency: "$",

5age: 18,

6Address: Address{ "山东", "济南"},

7}

8//提阶

9emp1.fullAddress() //山东 济南,提阶相当于直接访问Address里的

10emp1.Address.fullAddress() //山东 济南

四、非结构类型的方法

非结构体类型也可以定义方法,不过这里需要注意一点。为了定义某个类型的方法,接收者类型的定义与方法的定义必须在同一个包中。

非结构体类型也可以定义方法,不过这里需要注意一点。为了定义某个类型的方法,接收者类型的定义与方法的定义必须在同一个包中。

因为必须在一个包中而int则在main包中我们没法去定义这个里为了简单直观,给int声明了别名

1//非结构体方法扩展

2typemyInt int

3

4func(a myInt)add(b myInt)myInt{

5returna + b

6}

7funcmain(){

8//调用扩展的方法

9num1 := myInt( 5)

10num2 := myInt( 10)

11sum := num1.add(num2)

12fmt.Println( "Sum is", sum)

13

14}

下面附上完整实例程序

1packagemain

2

3import(

4"fmt"

5"math"

6)

7

8//Employee 需要添加注释或者改成非导出变量(首字母小写)

9typeEmployee struct{

10name string

11currency string

12salary int

13age int

14Address

15}

16

17//Address 代码规范

18typeAddress struct{

19city string

20state string

21}

22

23//Rectangle 代码规范

24typeRectangle struct{

25width float32

26height float32

27}

28

29//Circle 代码规范

30typeCircle struct{

31radius float32

32}

33

34//Employee 的方法

35func(e Employee)displaySalary(){

36fmt.Println(e)

37}

38func(e Employee)changeName(newName string){

39e.name = newName

40}

41func(e *Employee)changeAge(newAge int){

42e.age = newAge

43}

44

45//Address 的方法

46func(add Address)fullAddress(){

47fmt.Println(add.city, add.state)

48}

49

50//Rectangle 的方法计算面积

51func(r Rectangle)getArea()float32{

52returnr.width * r.height

53}

54

55//Circle 的方法

56func(c Circle)getArea()float32{

57returnmath.Pi * c.radius * c.radius

58}

59

60//非结构体方法扩展

61typemyInt int

62

63func(a myInt)add(b myInt)myInt{

64returna + b

65}

66funcmain(){

67//调用方法

68emp1 := Employee{

69name: "张三",

70salary: 6000,

71currency: "$",

72age: 18,

73Address: Address{ "山东", "济南"},

74}

75emp1.displaySalary()

76

77fmt.Println( "Before call changeName ", emp1.name)

78//修改名字,未发生变化因为是值传递

79emp1.changeName( "zhangsan")

80fmt.Println( "After call changeName ", emp1.name) //After call changeName 张三

81

82fmt.Println( "Before change age", emp1.age)

83//利用指针来修改年龄

84emp1.changeAge( 50)

85fmt.Println( "After change age", emp1.age) //After change age 50

86

87//提阶

88emp1.fullAddress() //山东 济南,提阶相当于直接访问Address里的

89emp1.Address.fullAddress() //山东 济南

90

91//计算面积

92re := Rectangle{ 20, 30}

93c := Circle{ 40}

94//两个类型调用同名方法

95fmt.Println(re.getArea())

96fmt.Println(c.getArea())

97

98//调用扩展的方法

99num1 := myInt( 5)

100num2 := myInt( 10)

101sum := num1.add(num2)

102fmt.Println( "Sum is", sum)

103

104}

ID:Golangweb