1、package的使用
golang编译器会将同一目录下的不同.go文件视作同一个包;也就是同一目录下的.go文件,定义package的名字要是同一个;
package pakName 此行必须写在第一行,且一个文件夹下的所有文件必须使用同一个包名,一个.go文件不能声明两个package。
2、声明变量
//若要声明变量,需要使用 var 关键字:
//声明 string 类型中的一个名为firstName 的变量
var firstName string
//一行中声明多个变量:
var firstName, lastName string
//通过在变量名称后面添加逗号 (,),就表示你将要声明其他变量。
//如要添加 int 类型的第三个变量,请按如下所示编写代码:
var firstName, lastName string
var age int
//另一种编写前一个语句的方法是在 var 关键字后面使用括号,就像通过一个专用块来声明变量一样,如下所示:
//一般用这种方式表明这些变量用于同一功能或者同属于同一模块
var (
firstName, lastName string
age int
)
//声明常量的关键字是 const。
const (
StatusOK = 0
StatusConnectionReset = 1
StatusOtherError = 2
)
3、初始化变量
//指定类型下的,初始化
var (
firstName string = "John"
lastName string = "Doe"
age int = 32
)
//使用具体值初始化该变量时,Go 会推断出其类型。
var (
firstName = "John"
lastName = "Doe"
age = 32
)
//Go 将推断出变量 firstName 和 lastName 的类型为 string,并且变量 age 属于 int 类型。
//在一行中,使用逗号将每个变量名称隔开,并对每个值执行相同的操作(按同一顺序),如下所示:
var (
firstName, lastName, age = "John", "Doe", 32
)
冒号等于号 (:=)声明并初始化变量
使用冒号等于号时,要声明的变量必须是新变量。
在函数内使用冒号等于号。 在声明函数外的变量时,必须使用 var 关键字执行此操作。
func main() {
firstName, lastName := "John", "Doe"
age := 32
println(firstName, lastName, age)
}
4、转义字符
转义字符的最常见示例:
• \n:新行
• \r:回车符
• \t:选项卡
• ':单引号
• ":双引号
• \:反斜杠
使用以下代码片段来测试转义字符:
fullName := "John Doe \t(alias \"Foo\")\n"
println(fullName)
你应会看到以下输出(包括新行):
John Doe (alias "Foo")
5、跳出循环
使用break lable 和 goto lable 都能跳出for循环;不同之处在于:break标签只能用于for循环,且标签位于for循环前面,goto是指跳转到指定标签处。
6、原子操作
atomic包的原子操作是通过 CPU 指令,也就是在硬件层次去实现的,性能较好,不需要像 mutex 那样记录很多状态。 当然,mutex 不止是对变量的并发控制,更多的是对代码块的并发控制,2 者侧重点不一样。
用原子操作来替换mutex锁,其主要原因是,原子操作由底层硬件支持,而锁则由操作系统提供的API实现。若实现相同的功能,前者通常会更有效率。
锁应当用来保护一段逻辑,对于一个变量更新的保护,原子操作通常会更有效率,并且更能利用计算机多核的优势,如果要更新的是一个复合对象,则应当使用atomic.Value封装好的实现。
部分源码举例:
// 需要 import "sync/atomic"
// Swap-实现了对值的原子交换
// SwapInt32 atomically stores new into *addr and returns the previous *addr value.
func SwapInt32(addr *int32, new int32) (old int32)
// SwapUintptr atomically stores new into *addr and returns the previous *addr value.
func SwapUintptr(addr *uintptr, new uintptr) (old uintptr)
// 比较并交换
// CompareAndSwapInt32 executes the compare-and-swap operation for an int32 value.
func CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool)
// Add-针对 int 和 uint 进行原子加值/减值(delta为负数)
// AddInt32 atomically adds delta to *addr and returns the new value.
func AddInt32(addr *int32, delta int32) (new int32)
// Load 方法是为了防止在读取过程中,有其他协程发起修改动作,影响了读取结果,常用于配置项的整个读取。
// LoadInt32 atomically loads *addr.
func LoadInt32(addr *int32) (val int32)
// Store-此类操作确保了写变量的原子性,避免其他操作读到了修改变量过程中的脏数据。
// StoreInt32 atomically stores val into *addr.
func StoreInt32(addr *int32, val int32)