Go语言基础闭包的原理分析示例详解

目录
  • 一. 闭包概述
  • 二. 代码演示
    • 运行结果
    • 代码说明

一. 闭包概述

  • 闭包就是解决局部变量不能被外部访问的一种解决方案
  • 闭包是把函数当作返回值的一种应用

二. 代码演示

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

// closure.go
package main
import (
	"fmt"
	"strings"
)
func main() {
	f := closure("http://", "com")
	fmt.Printf("%T %p \n", f, f)
	fmt.Println(f("baidu"))
	fmt.Println(f("qq"))
	fmt.Println(f("alipay.com"))
	fmt.Println("")
	f1 := closure("http://", "com")
	fmt.Printf("%T %p \n", f1, f1)
	fmt.Println(f1("baidu"))
	fmt.Println(f1("qq"))
	fmt.Println(f1("alipay.com"))
}
func closure(prefix, suffix string) func(url string) string {
	pre, suf := prefix, fmt.Sprintf(".%s", suffix)
	return func(url string) string {
		fmt.Printf("%p %p ", &pre, &suf)
		if !strings.HasPrefix(url, pre) {
			url = fmt.Sprintf("%s%s", pre, url)
		}
		if !strings.HasSuffix(url, suf) {
			url = fmt.Sprintf("%s%s", url, suf)
		}
		return url
	}
}

运行结果

$ go run closure.go
func(string) string 0x493560
0xc0000301d0 0xc0000301e0 http://baidu.com
0xc0000301d0 0xc0000301e0 http://qq.com
0xc0000301d0 0xc0000301e0 http://alipay.com

func(string) string 0x493560
0xc0000302d0 0xc0000302e0 http://baidu.com
0xc0000302d0 0xc0000302e0 http://qq.com
0xc0000302d0 0xc0000302e0 http://alipay.com

代码说明

第 2 行 返回的是变量 f 函数的 类型地址 ,函数在Go 语言中是引用类型。如果学过Java语言就知道,Java对象的内存空间有栈、堆、方法区、静态区。

第 3 - 5 行返回的是 pre suf 两个变量的地址,每一次调用是pre suf 地址都是不变的。

第 6 - 9 行这是新声明的 f1 变量,这时候 pre suf 的地址和上一次 f 的里面的 pre suf 地址是不一样的。

因为我们创建引用类型的变量时,其实只是一个标头值,标头值里包含一个指针,指针指向底层的数据,它所指向的底层结构没有被复制传递,这也引用类型比值类型传递更高效的原因。

以上就是Go语言基础闭包的底层原理及实例详解的详细内容,更多关于Go语言闭包的资料请关注我们其它相关文章!

(0)

相关推荐

  • Golang开发库的集合及作用说明

    目录 golang用于创建和发送电子邮件的库 golang处理日期和时间的库 数据库迁移 Go语言实现的数据库 golang通用数据结构及算法 golang用于进行配置解析的库 golang认证和授权库 golang用于操作音频的库 golang代码中嵌入其他语言的包 Go日志库 golang操作表单的库 Go实现消息系统的库 golang用于创建和发送电子邮件的库 douceur - HTML 邮件中的内联 CSS email - 一个健壮的.灵活的 email 库 Go-dkim - DKI

  • 举例讲解Go语言中函数的闭包使用

    和变量的声明不同,Go语言不能在函数里声明另外一个函数.所以在Go的源文件里,函数声明都是出现在最外层的. "声明"就是把一种类型的变量和一个名字联系起来. Go里有函数类型的变量,这样,虽然不能在一个函数里直接声明另一个函数,但是可以在一个函数中声明一个函数类型的变量,此时的函数称为闭包(closure). 例: 复制代码 代码如下: packagemain   import"fmt"   funcmain(){     add:=func(baseint)fun

  • Golang高性能持久化解决方案BoltDB数据库介绍

    目录 1. 介绍Bolt 2. 示例 3. 示例分析 4. 总结 1. 介绍Bolt BoltDB是纯Go语言实现的持久化解决方案,保存数据至内存映射文件.称之为持久化解决方案不是数据库,因为数据库这个词有很多额外功能是bolt所不具备的.正是因为缺乏这些功能使得bolt如此优雅.好用. Bolt就是一个Go包.无需在系统中安装,开始编码前也无需配置,什么都不需要,仅需要go get github.com/boltdb/bolt,然后import "github.com/boltdb/bolt&

  • Go语言net包RPC远程调用三种方式http与json-rpc及tcp

    目录 一.服务端 二.http客户端 三.TCP客户端 四.json客户端 五.运行结果 rpc有多种调用方式,http.json-rpc.tcp 一.服务端 在代码中,启动了三个服务 package main import ( "log" "net" "net/http" "net/rpc" "net/rpc/jsonrpc" "sync" ) //go对RPC的支持,支持三个级别:T

  • Go语言基础单元测试与性能测试示例详解

    目录 概述 单元测试 代码说明如下 问题 注意 性能测试 基本使用 自定义测试时间 概述 测试不是Go语言独有的,其实在很多语言都有测试,例如:Go.Java.Python- 要想成为一名合格的大牛,这是程序员必须具备的一项技能,特别是一些大公司,这是加分的一项,主要有如下优点: 代码可以随时测试,保证代码不会产生错误 写出更加高效的代码 testing文档 Testing_flags文档 单元测试 格式:func TestXXX(t *testing.T) //add.go package c

  • 深入理解Go语言中的闭包

    闭包 在函数编程中经常用到闭包,闭包是什?它是怎么产生的及用来解决什么问题呢?先给出闭包的字面定义:闭包是由函数及其相关引用环境组合而成的实体(即:闭包=函数+引用环境).这个从字面上很难理解,特别对于一直使用命令式语言进行编程的程序员们. Go语言中的闭包 先看一个demo: func f(i int) func() int { return func() int { i++ return i } } 函数f返回了一个函数,返回的这个函数就是一个闭包.这个函数中本身是没有定义变量i的,而是引用

  • Go语言基础闭包的原理分析示例详解

    目录 一. 闭包概述 二. 代码演示 运行结果 代码说明 一. 闭包概述 闭包就是解决局部变量不能被外部访问的一种解决方案 闭包是把函数当作返回值的一种应用 二. 代码演示 总体思想为:在函数内部定义局部变量,把另一个函数当作返回值,局部变量对于返回值函数相当于全部变量,所以多次调用返回值函数局部变量的值跟随变化. // closure.go package main import ( "fmt" "strings" ) func main() { f := clo

  • Go语言基础函数基本用法及示例详解

    目录 概述 语法 函数定义 一.函数参数 无参数无返回 有参数有返回 函数值传递 函数引用传递 可变参数列表 无默认参数 函数作为参数 二.返回值 多个返回值 跳过返回值 匿名函数 匿名函数可以赋值给一个变量 为函数类型添加方法 总结 示例 概述 函数是基本的代码块,用于执行一个任务 语法 函数定义 func 函数名称( 参数列表] ) (返回值列表]){ 执行语句 } 一.函数参数 无参数无返回 func add() 有参数有返回 func add(a, b int) int 函数值传递 fu

  • Go语言基础设计模式之策略模式示例详解

    目录 概述 针对同一类型问题的多种处理方式 一.不使用策略模式 二.策略模式 UML 总结 示例 概述 定义一系列算法,将每个算法封装起来.并让它们能够相互替换.策略模式让算法独立于使用它的客户而变化. 针对同一类型问题的多种处理方式 一.不使用策略模式 package main import "fmt" type User struct { Name string } func (this User) travel(t string) { switch t { case "

  • Go语言基础go fmt命令使用示例详解

    go fmt 命令主要是用来帮你格式化所写好的代码文件[很多第三方集成软件都是使用了go fmt命令] 一.使用: go fmt <文件名>.go 使用go fmt命令,更多时候是用gofmt,而且需要参数 -w,否则格式化结果不会写入文件.gofmt -w src,可以格式化整个项目. 二.参数介绍 -l 显示那些需要格式化的文件 -w 把改写后的内容直接写入到文件中,而不是作为结果打印到标准输出. -r 添加形如"a[b:len(a)] -> a[b:]"的重写规

  • Go语言基础go install命令使用示例详解

    目录 go install 一.使用 二.包名和目录名的关系 三.注意 go install 编译并安装代码包,对于库,会生成目标库文件,并且放置到GOPATH/pgk目录下. 对于可执文件,会生成目标可执行文件,并且放置到GOPATH/bin目录下 一.使用 命令 描述 go install lib 编译安装package lib,会为main包在bin下生成可执行exe文件 go install lib2 lib/util 同时编译安装lib2和lib/util两个package. 二.包名

  • Go语言基础类型及常量用法示例详解

    目录 基础类型 概述 按类别有以下几种数据类型 数值类型 派生类型 变量 概述 单个变量声明 多个变量声明 基础类型 概述 在 Go 编程语言中,数据类型用于声明函数和变量.数据类型的出现时为了把数据分成所需要用大数据的时候才需要申请大内存,这样可以充分的列用内存. 按类别有以下几种数据类型 数值类型 布尔型 bool:布尔型的值只可以是常量 true 或者 false,默认值为 false. 字符串类型 string:编码统一为 UTF-8 编码标识 Unicode 文本,默认值为空字符串.

  • Go语言基础枚举的用法及示例详解

    目录 概述 一.普通枚举 二.自增枚举 注意 代码 概述 将变量的值一一列举出来,变量只限于列举出来的值的范围内取值 Go语言中没有枚举这种数据类型的,但是可以使用const配合iota模式来实现 一.普通枚举 const ( cpp = 0 java = 1 python = 2 golang = 3 ) 二.自增枚举 iota只能在常量的表达式中使用 fmt.Println(iota) //undefined: iota 它默认开始值是0,const中每增加一行加1 const ( a =

  • Go底层channel实现原理及示例详解

    目录 概念: 使用场景: 底层数据结构: 操作: 创建 发送 接收 关闭 案例分析: 概念: Go中的channel 是一个队列,遵循先进先出的原则,负责协程之间的通信(Go 语言提倡不要通过共享内存来通信,而要通过通信来实现内存共享,CSP(Communicating Sequential Process)并发模型,就是通过 goroutine 和 channel 来实现的) 使用场景: 停止信号监听 定时任务 生产方和消费方解耦 控制并发数 底层数据结构: 通过var声明或者make函数创建

  • Go逃逸分析示例详解

    目录 引言大纲 逃逸分析 内存管理 栈 堆 堆和栈的对比 加锁 性能 缓存策略 逃逸分析优势 逃逸分析原则 逃逸分析举例 1.参数是interface类型 2. 变量在函数外部有引用 3. 变量内存占用较大 4. 变量大小不确定时 思考题 总结 引言大纲 这个月我会整理分享一系列后端工程师求职面试相关的文章,知识脉络图如下: JAVA/GO/PHP 面试常问的知识点 DB:MySql PgSql Cache: Redis MemCache MongoDB 数据结构 算法 微服务&高并发 流媒体

  • 无UI 组件Headless框架逻辑原理用法示例详解

    目录 概述 精读 总结 概述 Headless 组件即无 UI 组件,框架仅提供逻辑,UI 交给业务实现.这样带来的好处是业务有极大的 UI 自定义空间,而对框架来说,只考虑逻辑可以让自己更轻松的覆盖更多场景,满足更多开发者不同的诉求. 我们以 headlessui-tabs 为例看看它的用法,并读一读 源码. headless tabs 最简单的用法如下: import { Tab } from "@headlessui/react"; function MyTabs() { ret

随机推荐