- bin目录下面存的是编译之后可执行的文件,pkg下面存放的是应用包,src下面保存的是应用源代码
- Go 语言不支持函数重载特性的主要原因是函数重载需要进行多余的类型匹配影响性能;
- 目前 Go 没有泛型(generic)的概念,也就是说它不支持那种支持多种类型的函数。不过在大部分情况下可以通过接口(interface),特别是空接口与类型选择(type switch,参考 第 11.12 节)与/或者通过使用反射(reflection,参考 第 6.8 节)来实现相似的功能。使用这些技术将导致代码更为复杂、性能更为低下,所以在非常注意性能的的场合,最好是为每一个类型单独创建一个函数,而且代码可读性更强。
- 指针也是变量类型,有自己的地址和值,通常指针的值指向一个变量的地址。所以,按引用传递也是按值传递
- 几乎在任何情况下,传递指针(一个32位或者64位的值)的消耗都比传递副本来得少。
- 尽量使用命名返回值:会使代码更清晰、更简短,同时更加容易读懂。
-
7.2.4 new() 和 make() 的区别
看起来二者没有什么区别,都在堆上分配内存,但是它们的行为不同,适用于不同的类型。
- new(T) 为每个新的类型T分配一片内存,初始化为 0 并且返回类型为*T的内存地址:这种方法 返回一个指向类型为 T,值为 0 的地址的指针,它适用于值类型如数组和结构体(参见第 10 章);它相当于
&T{}
。 - make(T) 返回一个类型为 T 的初始值,它只适用于3种内建的引用类型:切片、map 和 channel(参见第 8 章,第 13 章)。
换言之,new 函数分配内存,make 函数初始化;
- new(T) 为每个新的类型T分配一片内存,初始化为 0 并且返回类型为*T的内存地址:这种方法 返回一个指向类型为 T,值为 0 的地址的指针,它适用于值类型如数组和结构体(参见第 10 章);它相当于
- 通过 buffer 串联字符串,这种实现方式比使用
+=
要更节省内存和 CPU,尤其是要串联的字符串数目特别多的时候。 - 想要在数组或切片中搜索一个元素,该数组或切片必须先被排序(因为标准库的搜索算法使用的是二分法)
- map 传递给函数的代价很小:在 32 位机器上占 4 个字节,64 位机器上占 8 个字节,无论实际上存储了多少数据。通过 key 在 map 中寻找值是很快的,比线性查找快得多,但是仍然比从数组和切片的索引中直接读取要慢 100 倍;所以如果你很在乎性能的话还是建议用切片来解决问题。
- 相对简单的情况下,通过使用 sync 包可以解决同一时间只能一个线程访问变量或 map 类型数据的问题。如果这种方式导致程序明显变慢或者引起其他问题,我们要重新思考来通过 goroutines 和 channels 来解决问题,这是在 Go 语言中所提倡用来实现并发的技术。
- Go 语言中,结构体和它所包含的数据在内存中是以连续块的形式存在的,即使结构体中嵌套有其他的结构体,这在性能上带来了很大的优势。
- 如果
File
是一个结构体类型,那么表达式new(File)
和&File{}
是等价的。 - 在一个结构体中对于每一种数据类型只能有一个匿名字段。
- 继承有两个好处:代码复用和多态。在 Go 中,代码复用通过组合和委托实现,多态通过接口的使用来实现:有时这也叫 组件编程(Component Programming)。
-
- 指针方法可以通过指针调用
- 值方法可以通过值调用
- 接收者是值的方法可以通过指针调用,因为指针会首先被解引用
- 接收者是指针的方法不可以通过值调用,因为存储在接口中的值没有地址
- 每个
interface {}
变量在内存中占据两个字长:一个用来存储它包含的类型,另一个用来存储它包含的数据或者指向数据的指针。 - 结构中只有被导出字段(首字母大写)才是可用反射设置的;
- Go 提供了动态语言的优点,却没有其他动态语言在运行时可能发生错误的缺点。
- Go 的接口提高了代码的分离度,改善了代码的复用性,使得代码开发过程中的设计模式更容易实现。
-
go实现:封装,继承和多态
-
封装(数据隐藏):和别的 OO 语言有 4 个或更多的访问层次相比,Go 把它简化为了 2 层(参见 4.2 节的可见性规则):
1)包范围内的:通过标识符首字母小写,
对象
只在它所在的包内可见2)可导出的:通过标识符首字母大写,
对象
对所在包以外也可见
类型只拥有自己所在包中定义的方法。
- 继承:用组合实现:内嵌一个(或多个)包含想要的行为(字段和方法)的类型;多重继承可以通过内嵌多个类型实现
- 多态:用接口实现:某个类型的实例可以赋给它所实现的任意接口类型的变量。类型和接口是松耦合的,并且多重继承可以通过实现多个接口实现。Go 接口不是 Java 和 C# 接口的变体,而且:接口间是不相关的,并且是大规模编程和可适应的演进型设计的关键。
-
try/catch
机制的使用太泛滥了,而且从底层向更高的层级抛异常太耗费资源。- Go 语言提供的垃圾回收器对并发编程至关重要。
- 不要通过共享内存来通信,而通过通信来共享内存。
- 永远不要使用一个指针指向一个接口类型,因为它已经是一个指针。
- channel关闭后sender的receiver操作:
(1)channel 已经被关闭,继续往它发送数据会导致panic: send on closed channel
:
(2)关闭的channel中不但可以读取出已发送的数据,还可以不断的读取零值:
(3)通过range
读取,channel关闭后for循环会跳出
(4)通过i, ok := <-c
可以查看Channel的状态,判断值是零值还是正常读取的值。
27. byte转string:
var x = []byte("Hello World!")
var y = *(*string)(unsafe.Pointer(&x))