继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

你可能不知道的一些Go Packages知识

holdtom
关注TA
已关注
手记 1703
粉丝 240
获赞 991


关于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的原创作品,如需转载,请注明出处,否则将追究法律责任


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP