关于Go Package
Go Packages 主要用来把相关的functions, variables, 和constants 组织到一起,这样你就可以很方便的迁移Packages和把它们用到自己的程序中。
注意除了main package, Go packages 不是自治程序,不能被编译成可执行文件。它们必须直接或者间接的被main package调用才能使用。
如果你直接执行一个没个package:
$ go run aPackage.go
go run: cannot run non-main package
关于Go function
匿名函数(anonymous functions)
匿名函数可以在内部定义,而不需要使用函数名,匿名函数通常被用来实现一些不需要太多代码的功能。在Go中 一个函数可以返回一个匿名函数,或者使用匿名函数作为它的其中一个参数。另外,匿名函数可以通过变量来访问。注意,在函数式编程术语中,匿名函数也称为闭包。
匿名函数具有较小的实现和功能集中点,这被认为是一种很好的做法。但是如果匿名函数没有功能集中点,那么你可能需要考虑使用常规函数。
注意不要在没有特殊需求的时候使用大量的匿名函数。
Go 函数可以返回多个值
func aFunction() (int, int, float64, float64) {
}
下面会有一个用一个functions.go来展示Go的匿名函数
package main
import (
"fmt"
"os"
"strconv"
)
func doubleSquare(x int) (int, int) { //函数返回两个int 类型的值
return x * x, x * x
}
func main() {
arguments := os.Args
if len(arguments) != 2 {
fmt.Println("The program needs 1 argument!")
return
}
y, err := strconv.Atoi(arguments[1])
if err != nil {
fmt.Println(err)
return
}
square := func (s int) int { //square的值为一个匿名函数
return s * s
}
fmt.Println("The square of", y, "is", square(y))
double := func (s int) int { //double的值为一个匿名函数
return s + s
}
fmt.Println("The double of", y, "is", double(y))
fmt.Println(doubleSquare(y))
d, s := doubleSquare(y)
fmt.Println(d, s)
}
上面的square 和 double 都持有一个匿名函数。不好的一点是,在以后的程序中你可以更改square,double或之后其他变量值为匿名函数的变量,这意味着这些变量的含义可以更改或计算成其他内容。
修改值为匿名函数变量的值是不推荐的,因为这可能是导致非常难以排查bug的主要原因。
如上面所示我们可以直接打印doubleSquare()的返回值,也可以给他们分配不同的变量进行打印。
执行functions.go:
$ go run function.go 1 21
The program needs 1 argument!
rMacBook:code mtsouk
$ go run functions.go 10
The square of 10 is 100
The double of 10 is 20
20 100
20 100
函数的返回值可以被命名
下面以returnNames.go为例,我们会把returnNames.go的代码分成3部分来进行讲解
Part 1
package main
import (
"fmt"
"os"
"strconv"
)
func nameMinMax(x, y int) (min, max int) {
if x > y {
min = y
max = x
} else {
min = x
max = y
}
return
}
在上面这段代码中函数namedMinMax并没有再return中指明返回值,但是由于我们在函数中定义了和函数返回值同名的变量,所以该函数会按照名称对应关系返回。
Part2
func minMax(x, y int) (min, max int) {
if x > y {
min = y
max = x
} else {
min = x
max = y
}
return min, max
}
在这段代码中我们在return 后面指定了返回值 mix,max。 注意改return中 min和max的顺序一定要先min,再max,因为该函数中 return并不是按照函数中的变量名和函数返回中的变量名对应关系返回的。
Part3: 即 returnNames.go的最后一段代码
func main() {
arguments := os.Args
if len(arguments) < 3 {
fmt.Println("The program needs at least 2 arguments!")
return
}
a1, _ := strconv.Atoi(arguments[1])
a2, _ := strconv.Atoi(arguments[2])
fmt.Println(minMax(a1, a2))
min, max := minMax(a1, a2)
fmt.Println(min, max)
fmt.Println(nameMinMax(a1, a2))
min, max = nameMinMax(a1, a2)
fmt.Println(min, max)
}
下面执行returnNames.go:
$ go run returnNames.go -20 1
-20 1
-20 1
-20 1
-20 1
指针可以作为函数的参数
下面以ptrFun.go进行讲解
package main
import "fmt"
func getPtr(v *float64) float64 {
return *v * *v
}
func main() {
x := 12.2
fmt.Println(getPtr(&x))
x = 12
fmt.Println(getPtr(&x))
}
上面的函数接收一个指针作为其参数,你可以使用"&"符号来获得一个变量的指针(变量的内存地址)。
执行ptrFun.go
$ go run main.go
148.83999999999997
144
如果你传入的不是指针,而是常规的12,即getPtr(12.12),程序回报下面错误:
$ go run ptrFun.go
# command-line-arguments
./ptrFun.go:15:21: cannot use 12.12 (type float64) as type *float64 in argument to getPtr
函数可以返回指针
下面以returnPtr.go为例:
package main
import "fmt"
func returnPtr(x int) *int {
y := x * x
return &y
}
func main() {
sq := returnPtr(10)
fmt.Println("sq:", *sq) // "*" 用来获取存储在sq内存地址中的值
fmt.Println("sq:", sq) // 该print会返回sq变量的内存地址,而不是int值
}
上面代码中我们定义了returnPtr函数,该函数返回一个init类型的指针。注意我们需要在return后面 &y来返回y变量的内存地址。
$ go run returnPtr.go
sq: 100
sq: 0xc420014088
函数的返回值可以是函数
下面以returnFunction.go为例:
package main
import "fmt"
func funReturnFun() func() int { //该函数的返回值为匿名函数
i := 0
return func() int {
i ++
return i * i
}
}
func main() {
//下面调用两次funReturnFun(),并把他们的返回值(匿名函数)分别赋值给i,j
//在下面的print中你会看到i,和 j是两个完全独立的变量,没有任何关联
i := funReturnFun()
j := funReturnFun()
//下面分通过i()和j()的方式调用了3次i变量,和2次j变量。
//注意i 和 j 都是通过调用 funRetrunFun()函数创建的,但是他们是完全独立的,不会共享任何东西。也不会互相干扰
fmt.Println("1:", i())
fmt.Println("2", i())
fmt.Println("j1", j())
fmt.Println("j2", j())
fmt.Println("3:", i())
}
下面执行returnFunction.go
$ go run returnFunction.go
1: 1
2: 4
j1: 1
j2: 4
3: 9
函数接收其他函数作为参数
下面以funFun.go进行讲解
package main
import "fmt"
func function1(i int) int { // 声明函数function1
return i + i
}
func function2(i int) int { //声明函数function2
return i * i
}
func funFun(f func(int) int,v int ) int { //该函数接收一个函数作为它的第一个参数,一个int类型作为第二个参数
return f(v) //把函数的第二个参数传给第一个参数函数
}
func main() {
fmt.Println("function1:", funFun(function1, 123)) //funciton1作为functFun的第一个参数
fmt.Println("function2", funFun(function2, 123)) //funciton1作为functFun的第一个参数
fmt.Println("Inline:", funFun(func(i int) int { return i * i * i }, 123)) //一个函数作为参数
运行上面的代码
$ go run funFun.go
function1: 246
function2: 15129
Inline: 1860867
©著作权归作者所有:来自51CTO博客作者woahjknes的原创作品,如需转载,请注明出处,否则将追究法律责任
共同学习,写下你的评论
评论加载中...
作者其他优质文章