从零开始学Go之函数(二):指针与方法

类型别名与类型定义:

类型别名:

type 类型别名 = 类型名

type TypeAlias = int

TypeAlias 只是 int 的别名,本质上 TypeAlias 与 int 是同一个类型

类型定义:

type 新类型名 类型

type NewInt int

NewInt 则是一个新的类型,虽然他的实例化可以被赋值int,但是不再是int

方法:

Go 没有类。不过你可以为结构体类型或者非结构体类型定义方法。

方法就是一类带特殊的接收者参数的函数。

func (方法名 类型定义名) 函数名 (函数参数列表) (函数返回值列表){

函数内部代码

}

type Vertex struct {
 X, Y float64
}
​
func (v Vertex) Abs() float64 {
 return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
​
type MyInt int
​
func (i MyInt) Abs() int {
 if i < 0 {
  return int(-i)
 }
 return int(i)
}
​
func main() {
 v := Vertex{3, 4}
 fmt.Println(v.Abs())
 i := MyInt(-2)
 fmt.Println(i.Abs())
}

运行结果:

5

-2

此时,只有当实例化后,才能调用Abs()函数。两个Abs()函数对应的类型是不同的,所以调用的结果也不同

方法只是个带接收者参数的函数。

指针:

简单解释一下,每个变量在运行时都会有一个在内存中的地址,而指针就是存储这个地址。

声明:

var [指针名] *[指针类型]

var p *int//一个int类型的指针
 
操作:

从指针取值:取地址操作符“&”

从值取地址:取值操作符“*”

 
使用例子:
func main() {
 var a int
 a = 1
 var b *int //或者是b:=new(int) 声明整型指针b
 b = &a  //b保存a的地址,即b指向a
 fmt.Println("a value=", a)
 fmt.Println("a address=", &a)
 fmt.Println("b address=", b)
 fmt.Println("b value=", *b)
 *b = 3 //通过指针修改值
 fmt.Println("a value=", a)
 fmt.Println("a address=", &a)
 fmt.Println("b address=", b)
 fmt.Println("b value=", *b)
}
a value= 1
a address= 0xc0420080a8
b address= 0xc0420080a8
b value= 1
a value= 3
a address= 0xc0420080a8
b address= 0xc0420080a8
b value= 3

可以发现地址没有改变,但是a和*b的值都同时改变了,由于b此时保存的是a的地址,当改变*b的值的时候实际就是在改变a的值。

 

方法的指针:

对于上一种方法,由于在函数中复制的是值,而本身没有改变,所以当需要改变实例化的结构体本身时,需要改变为方法的指针。

func (方法名 *类型定义名) 函数名 (函数参数列表) (函数返回值列表){

函数内部代码

}

type Vertex struct {
 X, Y float64
}
​
func (v Vertex) Abs() float64 {
 v.X=6
 v.Y=8
 return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
​
func (v *Vertex) NewAbs() float64 {
 v.X=6
 v.Y=8
 return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
​
func main() {
 v := Vertex{3, 4}
 fmt.Println(v.Abs(), v)
 fmt.Println(v.NewAbs(), v)//v的值已经改变
}

运行结果:

10 {3 4}

10 {6 8}

这里需要注意的是NewAbs()中方法接收者是指针,虽然main函数中接受者v不是地址,但是Go会自动解释为(&v).NewAbs()

猜你喜欢

转载自www.cnblogs.com/VingB2by/p/11117732.html