惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Security Latest
Security Latest
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Stack Overflow Blog
Stack Overflow Blog
WordPress大学
WordPress大学
N
Netflix TechBlog - Medium
GbyAI
GbyAI
云风的 BLOG
云风的 BLOG
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
宝玉的分享
宝玉的分享
博客园 - 【当耐特】
C
Cyber Attacks, Cyber Crime and Cyber Security
雷峰网
雷峰网
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
Threat Research - Cisco Blogs
NISL@THU
NISL@THU
Spread Privacy
Spread Privacy
P
Proofpoint News Feed
J
Java Code Geeks
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
MyScale Blog
MyScale Blog
T
Tor Project blog
P
Proofpoint News Feed
C
CERT Recently Published Vulnerability Notes
P
Privacy & Cybersecurity Law Blog
MongoDB | Blog
MongoDB | Blog
Simon Willison's Weblog
Simon Willison's Weblog
C
Cybersecurity and Infrastructure Security Agency CISA
L
LINUX DO - 热门话题
小众软件
小众软件
G
GRAHAM CLULEY
P
Privacy International News Feed
AWS News Blog
AWS News Blog
Know Your Adversary
Know Your Adversary
P
Palo Alto Networks Blog
人人都是产品经理
人人都是产品经理
S
Schneier on Security
Scott Helme
Scott Helme
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
B
Blog RSS Feed
T
The Exploit Database - CXSecurity.com
Recent Announcements
Recent Announcements
E
Exploit-DB.com RSS Feed
C
CXSECURITY Database RSS Feed - CXSecurity.com
U
Unit 42
The Register - Security
The Register - Security
S
Securelist
Martin Fowler
Martin Fowler
Project Zero
Project Zero
大猫的无限游戏
大猫的无限游戏
Cisco Talos Blog
Cisco Talos Blog

博客园 - 自然洒脱

MiniMax 权益码 Token Plan 套餐 9 折优惠 go语言context包 go语言通道 go语言GMP模型 go语言mongodb操作 go语言gorm的CRUD go语言gorm go语言mysql驱动 go语言log相关 go语言包管理 go语言时间相关 go语言序列化和反序列化 go语言的"面向对象" go语言结构体排序 go语言异常处理 go语言接口 go语言结构体(二) go语言结构体(一) go语言递归函数及defer
go语言函数作用域及匿名函数
自然洒脱 · 2023-06-25 · via 博客园 - 自然洒脱

作用域

函数会开辟一个局部作用域,其中定义的标识符仅能在函数之中使用,也称为标识符在函数中的可见范围。 这种对标识符约束的可见范围,称为作用域。

对外不可见、向内穿透、就近原则。

1、语句块作用域

if、for、switch等语句中定义的变量,可以认为就是该语句块的变量,作用域仅在该语句块中。if、swith、select语句中的每个子句都被视为一个隐式的代码块。

    s0 := []int{1, 2, 3, 4, 5}
    if s0[1] >10 {
        var a int =10
        fmt.Println(10)
    }else if s0[1] < 10 {
        fmt.Println(a) // 此处对变量a不可见
    }

2、显式的块作用域

在任何一个大括号中定义的标识符,其作用域只能在这对大括号中。

    {
        var a string = "你好gopher"
        const b = 123
        c := 'a'
    fmt.Println(a,b,c)
    }
    fmt.Println(a,b,c) // 此处对abc变量不可见

3、universe块

宇宙块,意思就是全局块,不过是语言内建的。预定义的标识符就在这个全局环境中,因此bool、int、 nil、true、false、iota、append等标识符全局可见,随处可用。

4、包块

每一个package包含该包所有源文件,形成的作用域。有时在包中顶层代码定义标识符,也称为全局标 识符。 所有包内定义全局标识符,包内可见。包的顶层代码中标识符首字母大写则导出,从而包外可见,使用 时也要加上包名。例如 fmt.Prinf() 。

// 下面是源码
func Println(a ...any) (n int, err error) {
    return Fprintln(os.Stdout, a...)
}

5、函数块

函数声明的时候使用了花括号,所以整个函数体就是一个显式代码块。这个函数就是一个块作用域。

const a = 123

var b string = "你好gopher"
var c = 768

func show() int {
    return c
}

func main() {
    fmt.Printf("%T %[1]v\n", a) // 这里的a是全局常量a,常量不可取地址
    a := "gopher"
    fmt.Printf("%T %[1]v %p\n", a, &a) // 这里的a是上面刚定义的局部变量a

    fmt.Printf("%T %[1]v %p\n", c, &c)
    c = 1024
    fmt.Printf("%T %[1]v %p\n", c, &c)
    var c = 'c'
    fmt.Printf("%T %[1]v %p\n", c, &c)
    fmt.Println(show()) // 这里show函数return的c是被修改成1024的全局变量的c
}

 标识符作用域

标识符对外不可见,在标识符定义所在作用域外是看不到标识符的

使用标识符,自己这一层定义的标识符优先,如果没有,就向外层找同名标识符——自己优先,由近及远

标识符对内可见,在内部的局部作用域中,可以使用外部定义的标识符——向内穿透

包级标识符,在所在包内,都可见;跨包访问,包级标识符必须大写开头,才能导出到包外,可以在包外使用 xx包名.VarName 方 式访问。例如 fmt.Print()

匿名函数

顾名思义,就是没有名字的函数。在函数定义中,把名字去掉就可以了。

func main() {
    func(x, y int) int {
        res := x + y
        fmt.Println(res)
        return res
    }(10, 11) // 定义并调用

    // 使用变量指向一个匿名函数,通过变量来调用以实现n次调用
    var add = func(x, y int) int {
        return x + y
    }
    fmt.Println(add(1, 2))
}

匿名函数主要作用是用作高阶函数中,它是传入的逻辑。若一个函数允许传入的参数是函数类型,就是 把操作逻辑外置。

高阶函数:形参定义为函数类型或返回值为函数类型,称为高阶函数

// cal并没有实现x,y的操作,而是交给了fu,而fu究竟做什么操
// 作由未来的使用者决定
func cal(x, y int, fu func(int, int) int) int {
    return fu(x, y)
}

func main() {
    add_re := cal(3, 5, func(a, b int) int {
        return a + b
    })
    mul_re := cal(10, 22, func(c, d int) int {
        return c * d
    })
    fmt.Println(add_re, mul_re)
}

函数嵌套

 outer中定义了另外一个函数inner,并且调用了inner。outer是包级变量,main可见,可以调 用。而inner是outer中的局部变量,outer中可见。