go的函数和方法

函数

参数

函数可以通过两种方式传递参数

  • 值传递:指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数
  • 指针传递:是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数
    **注意1:**无论是值传递,还是引用传递,传递给函数的都是变量的副本,不过,值传递是值的拷贝。引用传递是地址的拷贝,一般来说,地址拷贝更为高效。而值拷贝取决于拷贝的对象大小,对象越大,则性能越低
    **注意2:**map、slice、chan、指针、interface默认以引用的方式传递

不定参数
不定参数传值 就是函数的参数不是固定的,后面的类型是固定的
Golang 可变参数本质上就是 slice,只能有一个,且必须是最后一个

func myfunc(args ...int) {    //0个或多个参数
}
func add(a int, args…int) int {    //1个或多个参数
}
func add(a int, b int, args…int) int {    //2个或多个参数
}

func myfunc(args ...interface{}) {
}

func test(s string, n ...int) string {
    var x int
    for _, i := range n {
        x += i
    }
    return fmt.Sprintf(s, x)
}

func main() {
    s := []int{1, 2, 3}
    res := test("sum: %d", s...)    // slice... 展开slice
    println(res)
}

任意类型的不定参数: 就是函数的参数和每个参数的类型都不是固定的,用interface{}传递任意类型数据是Go语言的惯例用法,而且interface{}是类型安全的

返回值
命名返回参数允许 defer 延迟调用通过闭包读取和修改

package main

func add(x, y int) (z int) {
    defer func() {
        z += 100
    }()

    z = x + y
    return
}

func main() {
    println(add(1, 2)) 
}

运行结果

103

显式 return 返回前,会先修改命名返回参数

package main

func add(x, y int) (z int) {
    defer func() {
		fmt.Println("print in defer, z:", z)
	}()

	z = x + y
	fmt.Println("return")
	return z + 200 // 执行顺序: (z = z + 200) -> (call defer) -> (return)
}

func main() {
    println(add(1, 2)) // 输出: 203
}

运行结果

return
print in defer, z: 203
203

方法

go的方法总是和定义的类型(结构体)绑定到一起,且隐式的将实例作为第一实参 (receiver),一个方法就是一个包含了接受者的函数,接受者可以是命名类型或者结构体类型的一个值或者是一个指针

// 参数列表和返回值列表可以省略
func (recevier type) methodName(参数列表)(返回值列表){}

值类型和指针类型方法

package main

import "fmt"

type User struct {
	Name string
}

// 方法
func (u User) valuePrint() {
	fmt.Println("name: ", u.Name)
}

func (u User) valueSet() {
	u.Name = "honghong"
}

// 方法
func (u *User) pointerPrint() {
	fmt.Println("name: ", u.Name)
}

func (u *User) pointerSet() {
	u.Name = "honghong"
}

func main() {
	fmt.Println("hello world")
	a := User{Name: "xiaoming"}
	b := &User{Name: "xiaohong"}
	fmt.Println("值方法(接受者为值时)")
	a.valueSet()
	a.valuePrint()
	b.valueSet()
	b.valuePrint()

	fmt.Println("指针方法(接受者为指针时)")
	a.pointerSet()
	a.pointerPrint()
	b.pointerSet()
	b.pointerPrint()
}

运行结果

值方法(接受者为值时)    
name:  xiaoming           
name:  xiaohong           
指针方法(接受者为指针时)
name:  honghong
name:  honghong

当方法的接受者不是一个指针时,该方法操作对应接受者的值的副本,即使使用指针实例调用方法,但是方法的接受者是值类型,所以方法内部操作还是对副本的操作,而不是指针操作,不会改变实例的内容
当方法的接受者是一个指针时,无论实例是值还是指针,方法都会对原实例进行操作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值