1.多变量赋值规则
多变量赋值时,先计算左边的所有值,然后从左到右依次赋值。
data, i := [3]int{0, 1, 2}, 0
i, data[i] = 2, 100 // (i = 0) -> (i = 2), (data[0] = 100)
2.iota的用法
iota从0开始计数,按行计数,是一个自增的常量值。
同一个常量组中可以提供多个iota,他们各自增长。
如果iota自增被打断,需显示恢复
const (
A = iota // 0
B // 1
C = "c" // c
D // c 与上一行相同。
E = iota // 4,显式恢复。注意计数包含了 C、D 两行。
F // 5
)
可通过自定义类型来实现枚举类型限制
type Color int
const (
Black Color = iota
Red
Blue
)
func test(c Color) {}
func main() {
c := Black
test(c)
x := 1
test(x) // Error: cannot use x (type int) as type Color in function argument
test(1) // 常量会被编译器自动转换。
}
3.字符串
字符串是不可变值类型,内部用指针指向UTF-8字节数组。
默认值是空字符串""
可以使用索引号访问某个字符,例如:s[2]
不可变类型,不能修改字符串
字节数组尾部不包含NULL
使用 ` 定义不做转义处理的字符串,支持跨行
代码:
s := `a
b\r\n\x00
c`
println(s)
输出:
a
b\r\n\x00
c
由于字符串无法修改,所以如果要修改字符串必须将字符串转为[]rune或[]byte,修改后再转为string,2种转换都会重新分配内存,并复制字符串,如果对性能要求很高那么可以使用下面的方式来做转换:
func SliceByteToString(b []byte) string {
return *(*string)(unsafe.Pointer(&b))
}
func StringToSliceByte(s string) []byte {
x := (*[2]uintptr)(unsafe.Pointer(&s))
h := [3]uintptr{x[0], x[1], x[1]}
return *(*[]byte)(unsafe.Pointer(&h))
}
4.指针
GO中方法中返回局部变量指针是安全的,不会导致内存泄漏,编译器会根据需要将其分配到GC HEAP上。
编译器会根据方法中返回的局部变量是否被外部应用来决定返回值是分配在栈上还是堆上。
func test() *int {
x := 100
return &x // 在堆上分配 x 内存。但在内联时,也可能直接分配在目标栈。
}
#5.使用空结构体作为channel的载体
在使用channel时需要定义channel的传输类型,当我们使用chan来通知其他线程时可以将传输类型定义为空结构体
ch1 := make(chan struct{})
ch2 := make(chan int)
使用空结构体的好处是GOLANG中不会对空结构体分配新的内存空间,GO中对空结构体使用固定的内存地址
5.结构体比较
结构体中如果包含slice/map/function类型时是不能直接做比较的。
结构体中如果包含指针当给struct中赋同一个地址时是可以直接比较的,并且是相等的,否则是不相等的。
结构体中如果只包含除上述类型的其他基本类型时则是可以直接比较的。
当结构体中包含slice/map/function时如果要比较可以使用reflect.DeepEqual来比较。