golang学习十:包的访问权限、变量作用域、闭包

包概述

  • • 包(package)是Go语言中组织单元.包是逻辑上的分组.而物理上的分组是不同的文件夹,文件夹和包一般是对应的

  • • 把多个文件放入同一个文件夹中,这些文件就是在同一个包中.

  • • 虽然允许源码文件的package和文件夹名不同但是最终编译后都会把文件的package编译成文件夹名称.所以为防止错误最好把文件的package和文件夹名称设置成相同的

  • • 一个Go语言项目必须要有main包,其他自定义名称的包个数任意,根据自己的需求即可.

  • • Go语言在寻找包时会从GOPATH/src 路径中寻找包,如果不存在去GOROOT/src(Go语言标准库源码所在文件夹)下找

  • • 不同包下资源可以相互访问,在导入其他包后,可以访问包下首字母大写的内容

  • • 同包下不同文件中全局资源可以随意访问

自定义包

  • • 新建项目后在项目下新建src文件夹,在src文件夹中新建demo文件

  • • 在demo文件中新建demo1.go和demo2.go文件

  • • demo1.go文件源码如下

package demo//包为demo

import "fmt"

func demo1(){
    fmt.Println("执行demo1")
}
  • • demo2.go文件源码如下

package demo//包为demo

import "fmt"

func Demo2()  {//函数名大写才能被其他包访问
    fmt.Println("执行demo2")
    demo1()//同包下内容任意访问
}
  • • 在项目根目录下新建main.go,源码如下

package main

import "demo"

func main() {
    demo.Demo2()
}
  • • 运行整个项目后,发现可以正常调用Demo2()函数

  • • 整个程序目录结构如下

    golang学习十:包的访问权限、变量作用域、闭包

变量作用域

  • • 变量声明位置决定了变量的可访问范围(哪里能调用到变量)

  • • Go语言中变量的有效范围如下

    • • 函数级别:变量声明在函数内部,只有在函数内部才能访问,称变量为局部变量

    • • package 包级别,在当前包下都可以访问.称变量为全局变量.变量声明在函数外面

    • • 应用级别,在整个应用下任何包内都可以访问.通过首字母大小写控制

局部变量

  • • 局部变量一定是在函数内部

  • • 在哪个{}内部声明,只能在哪个{}内部访问

func test1() {
    i := 2 //从此处开始到test1结束}任何位置都能调用i
    if i>=2{
        j:=3
        fmt.Println(i+j)//此处可以访问i
    }
    fmt.Println(i)
    //fmt.Println(j)//此处不能调用j,超出声明j时{}外
}
func test2() {
    fmt.Println(i) //此处无法调用test1()中的i
}

全局变量

  • • 全局变量声明到函数外部,整个包都可以访问

  • • 如果全局变量首字母大写,跨包也可以访问.

  • • 声明全局变量时规范是

var (
    变量名
    变量名=值
)
  • • 全局变量代码示例

var (
    name = "smallming"
    age  = 17
)

func demo1() {
      fmt.Println("名字:",name)
}

func demo2() {
      fmt.Println("年龄:",age)
}

闭包概述

  • • 闭包不是Go语言独有的概念,在很多编程语言中都有闭包

  • • 闭包就是解决局部变量不能被外部访问一种解决方案

  • • 是把函数当作返回值的一种应用

代码演示

  • • 总体思想为:在函数内部定义局部变量,把另一个函数当作返回值,局部变量对于返回值函数就相当于全局变量,所以多次调用返回值函数局部变量的值跟随变化

package main

import "fmt"

func main() {
    //res其实就是test1返回值函数,和之前匿名函数变量一个道理
    res := test1()
    fmt.Println(res()) //输出2
    fmt.Println(res()) //输出3
    fmt.Println(res()) //输出4
}

//注意此处,返回值类型是func int
func test1() func() int {
    i := 1
    return func() int {
        i = i + 1
        return i
    }
}
  • • 如果重新调用test1()会重新声明及赋值局部变量i

package main

import "fmt"

func main() {
    f := test1()
    fmt.Println("f的地址", f) //输出匿名函数地址
    fmt.Println("f:", f()) //调用匿名函数输出2
    fmt.Println("f:", f()) //调用匿名函数输出3
    k := test1()
    fmt.Println("k的地址", k) //输出匿名函数地址,与f相等
    fmt.Println("k:", k()) //调用匿名函数输出2
    fmt.Println("f:", f()) //输出:4
    fmt.Println("k:", k()) //输出:3
}

func test1() func() int {
    i := 1
    return func() int {
        i++
        // 每调用一次test1()输出的地址不一样
        fmt.Println("i的地址:", &i)
        return i
    }
}


原文始发于微信公众号(杂食的程序员):golang学习十:包的访问权限、变量作用域、闭包

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/247301.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!