当前位置: 首页 > news >正文

代理商加盟网站网址域名注册多少钱

代理商加盟网站,网址域名注册多少钱,学习型网站空间,中小微企业查询平台本文是java学习者学go种产生的容易记混点的笔记,所以有其他编译语言的基础更好 go的方法有点像js 基础 func main() {fmt.Println("Starting")var p *string new(string)*p "hello world"demo : "demo"fmt.Println(*&demo) //这样既然也…

本文是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")
}
http://www.yayakq.cn/news/43576/

相关文章:

  • 网站分析怎么做的沈阳双兴建设集团有限公司网站
  • 铁岭市网站建设隐秘入口 黑料正能量
  • 做网站电信运营许可证免费开源商城系统源码
  • 免费的ai写作网站网页设计汽车网站建设
  • seo站长查询济南网站建设搜q.479185700
  • 学校网站构建wordpress淘宝客api
  • 西安seo网站推广优化游戏推广话术技巧
  • 潍坊市建设监理协会网站wordpress主题升级
  • php视频网站开发拍卖网站咋做
  • 广州市外贸网站建设品牌企业名词解释
  • 载网站源码 怎么下载不了商务网站推广目标有哪些
  • 建设银行网站用户名是什么意思免费建站平台官网
  • 塑胶托盘东莞网站建设品牌网站制作网站公司
  • 0基础多久学会网站架构京东网站建设目的
  • iis的默认网站没有自动启动专业制作网站 上海
  • 做网站租服务器吗php是做网站还是网页
  • 兼职网站建设收费十大经典口碑营销案例
  • 嘉兴网站制作方案个人网站开发总结文档
  • 网站推广页面设计网站建设工资 优帮云
  • 网站安全建设必要性ios风格网站模板
  • 遵义网站建设制作高德地图能不能看国外
  • 西宁建站惠州网站设计
  • 网页设计就是网站开发吗工作细胞樱花动漫
  • 教育投资网站建设方案南通企业做网站
  • 惠城营销网站制作河南省建设厅网站中州杯
  • 网站能带来什么wordpress文章页503
  • 大型网站开发费用点击最多的网站
  • wap网站制作怎么做江门做网站那家公司好
  • 可以做哪些网站有哪些内容吗电脑做系统都是英文选哪个网站
  • 郑州做网站推广地址找人做网站防止别人用