go学习笔记

1.接口

1.定义

接口是一组方法的集合

2.构成

例子:

type Something interface {
	//具体需要实现的方法,例如
	Speak() string
	Myspeak() func()
}

在这个例子中,Something只是一个接口类型的名称,它没有实际意义。它只是一个占位符,用于表示实现该接口的类型必须实现的方法。这种方式可以让我们定义一个通用的接口类型,然后让不同的类型实现该接口,从而实现多态和灵活的设计。

3.实现

接口的实现是隐式的,只要某一个类型实现了这些方法就是实现了这个接口
例子:接上文

type Dog struct{}
type Cat struct{}
func (d Dog) Speak() string{
	return "woof!"
}
func (d Dog) Myspeak() func (){
	return fmt.Println("I am a dog")
}
func (c *Cat) Myspeak() func (){
	return fmt.Println("I am a cat")
}

4.接收者

上文中的"c Cat"和"d *Dog"都是接口方法的接收者,他们的数据类型分别是值和指针。如果方法的接收者是值类型,无论调用者是对象还是对象指针,修改的都是对象的副本,不影响调用者。如果方法的接收者是指针类型,则调用者修改的是指针指向的对象本身。这意味着,如果您想修改调用者的对象,您应该使用指针接收者。如果您只是想读取调用者的对象,您应该使用值接收者。
但是,若接收者是值类型,但是调用者是指针类型,可以正常运行;反之不行。
例子:书接上文

//可行
var a Dog 
var speak Speak = &a
a.Speak()

是可行的,而下面的例子是不可行的。

//不可行
var b Cat
var speak Speak = b
b.Speak()

对结构体而言不可行,但是有隐式的指针转换:
你好,这是一个很好的问题。Go语言中的接口是一种抽象类型,它可以持有任何实现了接口方法的具体类型的值。接口的值由两部分组成:一个指向具体类型的指针,和一个记录该类型信息的描述符。所以,当你传递一个变量的值给一个接口参数时,接口会自动获取该变量的地址,并保存它作为指针部分。这样,接口就可以调用具体类型的方法,而不需要你显式地传递指针。这也是为什么你可以用一个值来满足一个需要指针接收者的接口方法12。

但是,这种隐式的指针转换只适用于接口类型,而不适用于具体类型。如果你有一个结构体类型,它有一个指针接收者的方法,那么你不能用该结构体的值来调用这个方法,因为结构体值没有地址3。你必须显式地获取结构体值的地址,并用指针来调用方法4。

2.切片

1.切片有3个字段的数据结构

这些数据结构包含Go语言需要操作底层数组的元数据。 这3个字段分别是指向底层数组的指针、切片访问的元素的个数(即长度)和切片允许增长到的元素个数(即容量)。

2.函数append会智能地处理底层数组的容量增长

在切片的容量小于1000个元素时,总是会成倍地增加容量。一旦元素个数超过1000,容量的增长因子会设为1.25,也就是会每次增加25%的容量。随着语言的演化,这种增长算法可能会有所改变。

3.新切片与原有的底层数组分离

如果在创建切片时设置切片的容量和长度一样,就可以强制让新切片的第一个 append 操作创建新的底层数组,与原有的底层数组分离。新切片与原有的底层数组分离后,可以安全地进行后续修改

4.(切片和map)与数组的区别

在函数间传递切片与传递数组不同,不论值传递再大的切片,传递的都是24字节,指针,长度和容量个8字节;但是传递大数组用指针传递。
Go语言中的映射(map)是一种用于存储一系列无序的键值对的数据结构,映射是一个引用类型,它的值是一个指向底层散列表的指针。当把一个映射赋值给另一个变量时,只会复制这个指针,而不会复制底层的数据。这样做的好处是,可以用很小的成本来复制映射,而不需要拷贝大量的键值对。这个特性和切片(slice)类似,切片也是一个引用类型,它的值是一个指向底层数组的指针。当把一个切片赋值给另一个变量时,也只会复制这个指针,而不会复制底层的数据。

5.map内部实现 ??

无序的原因是映射的实现使用了散列表

6.切片、函数以及包含切片的结构类型不能作为映射的键

因为具有引用语义,使用这些类型会造成编译错误
【这段文字的意思是,Go语言中的映射(map)是一种用于存储一系列无序的键值对的数据结构,映射的键必须是可以使用和!=运算符进行比较的类型,否则会导致编译错误。切片、函数以及包含切片的结构类型都是引用类型,它们的值是一个内存地址,而不是实际的数据。这些类型不能直接使用和!=运算符进行比较,因为它们可能指向相同的底层数据,但却有不同的地址。如果使用这些类型作为映射的键,就无法正确地判断键是否相等,也就无法正确地存取映射中的值。】

7.nil映射不能用于存储键值对

可以通过声明一个未初始化的映射来创建一个值为nil的映射(称为nil映射 )。
dict := make(map[string]int)就是用make函数创建了一个键类型为string,值类型为int的映射,并把这个映射的引用赋值给了变量dict。由于make函数会初始化一个值,所以使用make生成的映射有初始值,即一个空的映射,不是nil。空的映射可以用于存储键值对,而nil映射则不能。

8.把一个键值对从映射里删除

使用内置的delete函数。

9.make的实现 ??

make函数会分配一块内存空间,并返回一个指向该空间的值,该值可以直接使用,而不需要像new函数那样返回一个指针。

make函数的实现原理是调用了底层的runtime包中的相关函数,根据不同的类型,分别调用了makeslice、makemap或makechan函数。这些函数会根据参数来计算需要分配的内存大小,并调用mallocgc函数来申请内存。然后,它们会初始化一些必要的字段,比如切片的长度、容量和指针,映射的哈希表和溢出桶,通道的缓冲区和元素类型等。最后,它们会返回一个包含了这些字段的结构体,作为make函数的返回值。

3.类型

1.":="只能够在函数内使用

2.方法

有接受者的函数被称为方法
方法包括值接受和指针接受;
值接受调用时会使用这个值的副本执行,当使用值接受时,可以使用指针类型来调用方法;
值接收者使用值的副本来调用方法,而指针接受者使用实际值来调用方法,也可以使用一个值来调用使用指针接收者声明的方法
如果给这个类型增加或者删除某个值,是要创建一个新值,还是要更改当前的值?如果是要创建一个新值,该类型的方法就使用值接收者。如果是要修改当前值,就使用指针接收者

3.结构类型5.3.3???

4.外部类型 内部类型 提升

4.并发

Go 语言里的并发指的是能让某个函数独立于其他函数运行的能力。当一个函数创建为goroutine时,Go 会将其视为一个独立的工作单元。这个单元会被调度到可用的逻辑处理器上执行。Go 语言运行时的调度器是一个复杂的软件,能管理被创建的所有goroutine并为其分配执行时间。这个调度器在操作系统之上,将操作系统的线程与语言运行时的逻辑处理器绑定,并在逻辑处理器上运行goroutine。调度器在任何给定的时间,都会全面控制哪个goroutine要在哪个逻辑处理器上运行。 

Go 语言的并发同步模型来自一个叫作通信顺序进程(Communicating Sequential Processes,CSP)的范型(paradigm)。CSP 是一种消息传递模型,通过在goroutine之间传递数据来传递消息,而不是对数据进行加锁来实现同步访问。用于在 goroutine 之间同步和传递数据的关键数据类型叫作通道(channel)。

5.go mod

还有go work 和 go sum ;go work 管理工作区,能够实现在不同项目之间的管理;
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值