go中的方法 func-----数据类型
本文是java学习者学go种产生的容易记混点的笔记,所以有其他编译语言的基础更好
go的方法有点像js
基础
func main() {fmt.Println("Starting")var p *string = new(string)*p = "hello world"demo := "demo"fmt.Println(*&demo) //这样既然也可以 &得到地址 也就是指针 在通过取值操作 得到数据fmt.Println(*p)for i := 0; i < 10; i++ {fmt.Println(i)if i == 5 {return //结束程序}}fmt.Println("Ending")}
多参数 多返回值形式
func add(a, b int) int {return a + b
}
func add(a, b int) int,int {return a + b,b
}
可变参数
形参部分是slice 动态数组
func add( b ...int) int {return 1
}
之所以可以不用写;就是因为底层go做了优化 所以定义方法时候 {必须跟在方法名字之后
细节-方法的传值
方法的参数传递分为值传递和引用传递(go种的引用传递是通过地址 /指针等方式)
值传递:实际形式参数接收的是数据的拷贝
引用传递:传递的是数据的引用,在函数内修改这个参数,原来的数据也会改变
为了简单记得,只要记得下下面的类型都是引用传递,其他都是值传递既可
- 切片
- 指针/地址
- 映射
- 通道
- 接口
基本就是复合类型加上指针接口 (函数虽然也是存储地址(函数体)的数据类型,但是作为参数也是把这个函数体地址作为值传递拷贝)所以想到达引用传递的效果就需要传递函数的地址(觉得头晕可见含后文)
在java种类传递的对象也是引用传递 但是在go中并不是,go种定义类是结构体的形式,然后创建实列对象有多种方法,只有使用new关键字会返回指针这个时候实列对象名字才是引用,其他方式实列的结构体的是数据本身
/*
*
只有下面的类型是引用传递 传递数据 修改数据会影响到原来的数据 其他的只可以通过传递地址指针实现方法修改元数据
理解引用传递
*/
package mainimport "fmt"// 1. 指针(Pointers)
func modifyValue(x *int) {*x = 42
}// 2. 切片(Slices)
func modifySlice(s []int) {s[0] = 42
}// 3. 映射(Maps)
func modifyMap(m map[string]int) {m["key"] = 42
}// 4. 通道(Channels)
func send(ch chan int) {ch <- 42
}// 5. 函数(Functions)
func callFunction(f func(int) int, x int) int {return f(x)
}func square(n int) int {return n * n
}// 6. 接口(Interfaces)
type Modifier interface {Modify()
}type Data struct {Value int
}func (d *Data) Modify() {d.Value = 42
}func modifyInterface(m Modifier) {m.Modify()
}func main() {// 测试指针a := 10fmt.Println("之前 (Pointer):", a)modifyValue(&a)fmt.Println("修改后 (Pointer):", a)// 测试切片b := []int{1, 2, 3}fmt.Println("之前 (Slice):", b)modifySlice(b)fmt.Println("修改后 (Slice):", b)// 测试映射c := map[string]int{"key": 1}fmt.Println("之前 (Map):", c)modifyMap(c)fmt.Println("修改后 (Map):", c)// 测试通道ch := make(chan int)go send(ch)fmt.Println("Received (Channel):", <-ch)// 测试接口d := &Data{Value: 10}fmt.Println("之前 (Interface):", d.Value)modifyInterface(d)fmt.Println("修改后 (Interface):", d.Value)
}
函数式编程
首先在go种,函数也可以作为参数以及返回值存在 为此就要介绍其他语言也有的匿名函数
匿名函数
func main() {a := 2//匿名函数的使用func(a *int) {container := []int{1, 2, 3, 4, 5}for _, value := range container {if value%2 == 0 {fmt.Println(value)}}}(&a) //即可调用b := func() int {return 1}()fmt.Println(b)f := func() int {fmt.Println("hello world")return 1}f()}
当然匿名参数存在的作用就是可以作为回调函数传参
值得注意的函数类型作为传递时候 申明格式就和go正常申明一样,但是申明go作为参数传递时候,这个时候的参数和返回值只需要申明类型即可
func main(){
r := opation(2, 3, func(a int, b int) int {return a*100 + b})
}
/*
*
主要用途是函数式编程 作用函数的参数和返回值类型可以省略,可以直接使用匿名函数
·回调函数 作为参数只需要申明返回值和参数类型即可
*/
func opation(a, b int, callback func(int, int) int) int {return callback(a, b)
}
闭包函数
首先解释闭包:
闭包(Closure)函数是一种函数,它可以访问其词法作用域(定义时的作用域)之外的变量。换句话说,闭包可以在其函数体内引用定义在函数外部的变量。这些变量称为自由变量。
/*
bitwiseIncrementer 是一个闭包函数,它返回一个函数,该函数每次调用时都会返回一个自增后的整数。
因为返回的函数引用了一个方法的变量 所以这个变量不会s被垃圾回收 所以这个函数可以一直使用
*/
func increment() func() int {a := 0f := func() int {a++return a}return f
}
main.go
ff := increment()fmt.Println(ff)fmt.Println(&ff)v1 := ff()fmt.Println(v1)v2 := ff()fmt.Println(v2)又调用了一个新的闭包函数 创建了新的内存空间 所以这个i也是新生成额变量ff2 := increment()fmt.Println(ff2())
猜猜会输出什么
流程是 :第一个函数返回了一个函数,而这个函数是闭包函数,正常来说函数使用后就被gc垃圾回收,但是由于返回的这个函数引用了这个变量,所以不会被gc,所以多次调用,自增还是改变的这个数据,而有再次调用这个代码得到一个自增函数时候,这个代码块的内容又是重新建立在新内存空间的,其中引用的a 又是新开辟的内存 所以又是1
那么输出这俩个自增函数
fmt.Println(ff)fmt.Println(ff2)
发现这俩个变量 不一样
函数类型深入
细心的可以发现,感觉函数和指针一样,装的数据是地址,指针装的是变量地址,而函数装的就是代码快的地址
由此可以再次测试
// 定义函数变量funcdemo1 := func() {fmt.Println("funcdemo1")}funcdemo2 := func() {fmt.Println("funcdemo2")}// 打印函数的指针地址fmt.Printf("函数代码块的地址 %p\n", funcdemo1)fmt.Printf("函数的地址 %p\n", &funcdemo1)
输出
可以证实,函数的值就是代码块的地址,而也可以对这个函数取地址
感觉和指针一样,指针也是装载地址的数据类型,也可以对指针取地址
funcdemo1 := func() {fmt.Println("funcdemo1")}funcdemo2 := func() {fmt.Println("funcdemo2")}a := 12P := &afmt.Println("对地址取指针的取值操作", *&a)fmt.Println("指针的数值", P)fmt.Println("指针的地址", &P)// 打印函数的指针地址fmt.Printf("函数代码块的地址 %p\n", funcdemo1)fmt.Printf("函数的地址 %p\n", &funcdemo1)
既然知道了这个底层,那么就可以实现俩个函数交换函数体
func main() {// 定义函数变量funcdemo1 := func() {fmt.Println("funcdemo1")}funcdemo2 := func() {fmt.Println("funcdemo2")}swapfunc(&funcdemo1, &funcdemo2)// 现在 funcdemo1 应该调用原来 funcdemo2 的内容funcdemo1() // 现在会调用 funcdemo2
}
func swapfunc(a, b *func()) {//调用传递的参数(*a)() //先对指针取值得到函数体然后执行fmt.Printf("之前的地址: a: %p, b: %p\n", *a, *b)*a, *b = *b, *a // 交换引用fmt.Printf("之后的地址: a: %p, b: %p\n", *a, *b)
}
确实是交换了函数体,这点和二重指针一样的,通过指针地址改变指针中装的地址,这里通过函数地址改变函数中装的函数体地址
而这样就不行
func swapfunc(a, b func()) {//调用传递的参数(a)()fmt.Printf("之前代码的地址: a: %p, b: %p\n", a, b)a, b = b, a // 交换引用fmt.Printf("之后的地址: a: %p, b: %p\n", a, b)
}
传递函数作为参数是,是值拷贝,传递的只是把形参作为副本,形参值是函数体的值,但是形参的地址不是传递的哪个函数地址,所以修改存储的函数体原来的函数不会改变,改变的只是形参
同理如果想要改变指针保存的地址,那么也是需要参数传递指针的地址
细节,如果是在最外部申明的函数,无法取地址
这样就会报错
func main() {//函数本身就是引用类型 无需地址符号即可提取地址fmt.Printf("函数的地址%T\n", funcdemo1)fmt.Printf("函数的地址%p\n", &funcdemo1)swapfunc(funcdemo1, funcdemo2)funcdemo1()}
func funcdemo1() {fmt.Println("funcdemo1")
}
func funcdemo2() {fmt.Println("funcdemo2")
}
相关文章:

go中的方法 func-----数据类型
本文是java学习者学go种产生的容易记混点的笔记,所以有其他编译语言的基础更好 go的方法有点像js 基础 func main() {fmt.Println("Starting")var p *string new(string)*p "hello world"demo : "demo"fmt.Println(*&demo) //这样既然也…...

408计算机网络--物理层
一、物理层概述 物理层是干嘛使得? 物理层解决如何在连接各种计算机的传输媒体上传输数据比特流,而不是指具体的传输媒体。 物理层主要任务是确定与传输媒体接口有关的一些特性。定义标准可以理解为插排上的两孔三孔 机械特性:定义物理连接…...

十年,亚马逊云科技合作伙伴网络开启AI新征程
“十年之前,你不认识我,我不认识你,因为云计算我们携手并肩;十年之后,我们仍是伙伴,更是朋友,因为人工智能再次起程。”这就是今天的亚马逊云科技与其合作伙伴的真实写照。 2024年是亚马逊云科技…...

基于Spring Boot的在线医疗咨询平台的设计与实现【附源码】
基于Spring Boot的在线医疗咨询平台的设计与实现 Design and implementation of the computer hardware mall based on Spring Boot Candidate: Supervisor: April 20th, 2024 学位论文原创性声明 本人郑重声明:所呈交的论文是本人在导师…...

星坤Type-A连接器:创新快充技术,引领电子连接!
快速发展的电子时代,消费者对电子设备的性能和便利性有着更高的要求。特别是在充电和数据传输方面,快充技术和高速传输已成为市场的新宠。中国星坤公司推出的Type-A连接器系列,以其卓越的性能和创新的设计,满足了市场对高效、稳定…...

入门JavaWeb之 Response 下载文件
web 服务器接收到客户端的 http 请求 针对这个请求,分别创建一个代表请求的 HttpServletRequest 对象,代表响应的 HttpServletResponse 对象 获取客户端请求过来的参数:HttpServletRequest 给客户端响应一些信息:HttpServletRe…...
Java自定义注解校验token并直接返回给前端状态
自定义注解 CheckToken import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) public int…...

C++ | Leetcode C++题解之第200题岛屿数量
题目: 题解: class Solution { private:void dfs(vector<vector<char>>& grid, int r, int c) {int nr grid.size();int nc grid[0].size();grid[r][c] 0;if (r - 1 > 0 && grid[r-1][c] 1) dfs(grid, r - 1, c);if (r …...

Linux安全配置
Linux系统审计信息有:系统启动日志(boot.log)、记录用户执行命令日志(acct/pacct)、记录使用su命令的使用(sulog)、记录当前登录的用户信息(utmp)、用户每次登陆和退出信…...
vue实现不预览PDF的情况下打印pdf文件
前景:默认情况,实现打印需要根据预览的内容进行打印。 但是当只有打印按钮存在,不预览文件内容的情况下,实现打印的话,可以通过后端接口返回服务器上PDF的地址,前端通过隐藏的iframe标签中src可实现预览功能 主要是根据…...

C++ | Leetcode C++题解之第199题二叉树的右视图
题目: 题解: class Solution { public:vector<int> rightSideView(TreeNode* root) {unordered_map<int, int> rightmostValueAtDepth;int max_depth -1;stack<TreeNode*> nodeStack;stack<int> depthStack;nodeStack.push(ro…...

[leetcode]圆圈中最后剩下的数字/ 破冰游戏
. - 力扣(LeetCode) class Solution {int f(int num, int target) {if (num 1) {return 0;}int x f(num - 1, target);return (target x) % num;} public:int iceBreakingGame(int num, int target) {return f(num, target);} };...

mysql数据库的管理
目录 一、常用的数据类型 二、MySQ数据库基础操作 1、登录数据库 2、查看当前的 MySQL 版本信息及连接用户名 3、查看当前服务器中的数据库 4.查看数据库中包含的表 5.查看表的结构(字段) 6、MySQL的6大约束属性 三、SQL…...
Java项目分层(持续更新中)
第一次更新时间2024.6.26 分包 实体类 功能类 工具类 分层 实体类层 我们要操作的对象,Book,Student... 控制层 控制请求转发 业务层 处理业务 数据层 连接数据库 处理数据 工具类层 JDBC等工具类 测试层 最终启动项目 明确我们所要做的业务之后&a…...
2024年软件测试面试题大全【答案+文档】
🍅 视频学习:文末有免费的配套视频可观看 🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 一、面试基础题 简述测试流程: 1、阅读相关技术文档(如产品PRD、UI设计…...
数据赋能(131)——体系:数据转换——概述、关注焦点
概述 数据转换是指将数据从一种格式、结构或类型转换为另一种格式、结构或类型的过程。 数据转换操作属于数据整理过程。 它通常涉及数据清洗、数据映射、数据合并、数据拆分等操作,以确保数据的正确性和一致性。 数据转换的目的在于将原始数据转换为更易于处理…...

【自然语言处理系列】掌握jieba分词器:从基础到实战,深入文本分析与词云图展示
本文旨在全面介绍jieba分词器的功能与应用,从分词器的基本情况入手,逐步解析全模式与精确模式的不同应用场景。文章进一步指导读者如何通过添加自定义词典优化分词效果,以及如何利用jieba分词器进行关键词抽取和词性标注,为后续的…...

TikTok短视频矩阵系统
随着数字化时代的到来,短视频已成为人们获取信息、娱乐消遣的重要渠道。TikTok,作为全球最受欢迎的短视频平台之一,其背后的短视频矩阵系统是支撑其成功的关键因素。本文将深入探讨TikTok短视频矩阵系统的构成、功能以及它在新媒体时代中的影…...
码题杯:我会修改图
原题链接:码题集OJ-我会修改图 题目大意:给你一张n个点(编号为1∼n),m条边(编号为1∼m)的无向图,图上每个点都有一个点权,权值分别为a1,a2,…,an&…...
MongoDB Map-Reduce 简介
MongoDB Map-Reduce 简介 MongoDB 是一个流行的 NoSQL 数据库,它使用文档存储数据,这些数据以 JSON 格式存储。MongoDB 提供了多种数据处理方法,其中 Map-Reduce 是一种用于批量处理和聚合数据的功能强大的工具。Map-Reduce 允许用户对大量数…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...

MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...