您好,登錄后才能下訂單哦!
Go Packages 主要用來把相關的functions, variables, 和constants 組織到一起,這樣你就可以很方便的遷移Packages和把它們用到自己的程序中。
注意除了main package, Go packages 不是自治程序,不能被編譯成可執行文件。它們必須直接或者間接的被main package調用才能使用。
如果你直接執行一個沒個package:
$ go run aPackage.go
go run: cannot run non-main package
匿名函數(anonymous functions)
匿名函數可以在內部定義,而不需要使用函數名,匿名函數通常被用來實現一些不需要太多代碼的功能。在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
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。