你可能不知道的一些GoPackages知识

关于Go Package

Go Packages 主要用来把相关的functions, variables, 和constants 组织到一起,这样你就可以很方便的迁移Packages和把它们用到自己的程序中。

10余年的将乐网站建设经验,针对设计、前端、开发、售后、文案、推广等六对一服务,响应快,48小时及时工作处理。网络营销推广的优势是能够根据用户设备显示端的尺寸不同,自动调整将乐建站的显示方式,使网站能够适用不同显示终端,在浏览器中调整网站的宽度,无论在任何一种浏览器上浏览网站,都能展现优雅布局与设计,从而大程度地提升浏览体验。创新互联从事“将乐网站设计”,“将乐网站推广”以来,每个客户项目都认真落实执行。

注意除了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

网页标题:你可能不知道的一些GoPackages知识
文章路径:http://scyanting.com/article/ieogog.html