函数
引用传递和值传递
引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
引用传递指针参数传递到函数内
package main
import "fmt"
func main() {
valChange()
fmt.Println("==============================")
refChange()
}
/* 引用传递值 */
func refChange(){
var a, b int = 100,200
fmt.Println(a)
fmt.Println(b)
/* &a 指向a指针,a变量的地址 */
swapRef(&a,&b)
fmt.Println(a)
fmt.Println(b)
}
func swapRef(x *int, y *int){
var temp int
temp = *x /* 保持x地址上的值 */
*x = *y /* 将y值赋给 x */
*y = temp /* 将temp值赋给 y */
}
/* 值传递 */
func valChange(){
var a, b int = 100,200
fmt.Println(a)
fmt.Println(b)
swap(a,b)
fmt.Println(a)
fmt.Println(b)
}
func swap(x, y int){
var temp int
temp = x
x = y
y = temp
}
函数和方法
Go中也有方法,它是一种特殊的函数,常用一般定义于struct之上(与struct关联、绑定),被称为struct的receiver。
方法示例:
package main
import "fmt"
type xingzhuang struct {
length float64
width float64
}
func (c *xingzhuang) area() float64 {
return c.length * c.width
}
func main() {
c := &xingzhuang{
2.5,
4.0,
}
fmt.Printf("%f\n",c.area())
}
其实方法本质上就是函数,但方法是关联了类型的,可以直接通过类型的实例去调用属于该实例的方法。
方法的注意事项:
1.方法的receiver type并非一定要是struct类型,type定义的类型别名、slice、map、channel、func类型等都可以。但内置简单数据类型(int、float等)不行,interface类型不行。
示例1. 通过类型别名的方式给int添加方法
package main
import "fmt"
##通过定义类型别名来给int类型的‘myint’类型添加成员方法
type myint int
func (i *myint) numadd(n int) int {
return n + 1
}
func main() {
n := new(myint)
fmt.Println(n.numadd(4))
}
示例2. 给slice类型添加方法
package main
import "fmt"
type myslice []int
func (v myslice) sumOfSlice() int {
sum := 0
for _, value := range v {
sum += value
}
return sum
}
func main() {
s := myslice{11, 22, 33}
fmt.Println(s.sumOfSlice())
}
2.struct结合它的方法就等价于面向对象中的类。只不过struct可以和它的方法分开,并非一定要属于同一个文件,但必须属于同一个包。所以,没有办法直接在int、float等内置的简单类型上定义方法,真要为它们定义方法,可以像上面示例中一样使用type定义这些类型的别名,然后定义别名的方法。
3.如果receiver是一个指针类型,则会自动解除引用
例如,下面的abc是指针,它会自动解除引用使得能直接调用属于newtype1实例的方法add()。
func (abc *newtype1) add() string {}
abc.add()
因为指针类型的方法会自动解除引用,可以使用指针对象直接调用对应类型(newtype1)的方法,那么我们通过(T Type)或(T *Type)定义的方法,都可以通过T来直接调用。那么T其实就是面向对象语言中的this,表示调用该实例的方法。如果愿意,自然可以使用this,例如(this Type),但这是可以随意的。