本文适合初学者阅读
- Go对参数的处理偏向保守, 不支持有默认值的可选参数, 不支持命名实参
- 调用时,必须按签名顺序传递指定类型和数量的实参, 就算以"_"命名的参数也不能忽略
- 在参数列表中,相邻的同类型参数可合并
func test(x, y int, s string, _bool) *int {
return nil
}
func main() {
test(1,2, "abc") //错误: not enough arguments in call to test
}
- 参数可视作函数局部变量, 因此不能在相同层次定义同名变量
func add(x, y int) int {
x := 100 //错误: no new variables on left side of :=
var y int // 错误: y redeclared in this block
return x + y
}
形参是指函数定义中的参数, 实参则是函数调用时所传递的参数. 形参类似函数的局部变量, 而实参则函数外部对象, 可以是常量, 变量, 表达式或函数等.
- 如果函数参数过多,建议将其重构为一个复合结构类型, 也算是变相实现可选参数和命名实参功能.
package main
// 可以作为数据库配置的方法
import (
"log"
"time"
)
type serverOption struct {
address string
port int
path string
timeout time.Duration
log *log.Logger
}
func newOption() *serverOption {
return & serverOption{
address: "0.0.0.0",
port: 3306,
path: "/var/test",
timeout: time.Second * 5,
log: nil,
}
}
func server(option *serverOption){}
func main() {
opt := newOption()
opt.port = 8080
server(opt)
}
变参
- 变参本质上就是一个切片. 只能接受一到多个同类型参数, 且必须放在列表尾部
package main
import "fmt"
func test(s string, a ...int) {
fmt.Printf("%T, %v\n", a, a)
}
func main() {
test("for test", 1, 2, 3, 4)
}
结果输出:
[]int, [1 2 3 4]
- 将切片作为变参时,须进行展开操作, 如果是数组,先将其转换为切片.
package main
import "fmt"
func test(a ...int) {
fmt.Println(a)
}
func main() {
a := []int{10, 20, 30}
test(a[:]...) // 转换为slice 后展开 TODO: 暂时还不能理解为什么这么做
}
- 既然变参是切片, 那么参数复制的切片自身, 并不包括底层数据, 也 因此可修改原数据, 如果需要, 可用内置函数COPY底层数据
package main
import "fmt"
func test(a ...int) {
for i := range a {
a[i] += 100
}
}
func main() {
a := []int{10, 20, 30}
test(a...)
fmt.Println(a)
}
结果输出:
[110 120 130]